#include "AssetBrowser.h"
#include <imgui.h>
#include "../../core/utils/EngineConfig.h"
#include "../../core/utils/utils.h"
#include "../../core/utils/AssetManager.h"
#include "../../Renderer.h"
#include "../../core/utils/Logging.h"
#include "../../core/utils/LoadingWindow.h"

// AssetBrowser.cpp (or a shared file)
#include <GLFW/glfw3.h>
#include <vector>
#include <string>

static std::vector<std::string> g_DroppedFiles;

void GLFWDropCallback(GLFWwindow *window, int count, const char *paths[])
{
    for (int i = 0; i < count; i++)
        g_DroppedFiles.emplace_back(paths[i]);
}

static std::string assetSearchQuery;
static bool sortAscending = true;
static int sortMode = 0; // 0 = Name, 1 = Type, 2 = UAID
static bool showImages = true;
static bool showAudio = true;
static bool showPrefabs = true;
static bool showFonts = true;

static std::vector<std::pair<std::string, AssetType>> pendingImports;
static bool showImportPopup = false;

void HandleFileDropsAsAssets()
{
    if (!g_DroppedFiles.empty())
    {

        for (auto &path : g_DroppedFiles)
        {
            std::string ext = GetFileExtension_Name(path);
            AssetType type = AssetManager::AssetTypeFromExtension(ext);

            pendingImports.emplace_back(path, type);
        }

        g_DroppedFiles.clear();

        showImportPopup = true;
    }
}

void ShowAssetBrowser()
{

    PROFILE_ENGINE_SCOPE("Editor::AssetBrowser");

    if (!g_engineConfig.settings.show_asset_window)
        return;

    // Open modal popup if needed
    if (showImportPopup)
        ImGui::OpenPopup("Import Assets");

    HandleFileDropsAsAssets();

    ImGui::Begin("Resources");

    if (ImGui::Button("Import Assets"))
    {
        std::vector<std::string> paths = OpenMultipleFilesDialog(FileDialogType::All);
        if (!paths.empty())
        {
            pendingImports.clear();

            for (const auto &path : paths)
            {
                std::string ext = GetFileExtension_Name(path);
                AssetType type = AssetManager::AssetTypeFromExtension(ext);

                pendingImports.emplace_back(path, type);
            }

            showImportPopup = true;
        }
    }

    ImGui::SameLine();

    if (ImGui::Button("Filters / Sort"))
        ImGui::OpenPopup("AssetBrowserFilterPopup");

    if (ImGui::BeginPopup("AssetBrowserFilterPopup"))
    {
        ImGui::Text("Sort By:");
        if (ImGui::Selectable("Name", sortMode == 0))
            sortMode = 0;
        if (ImGui::Selectable("Type", sortMode == 1))
            sortMode = 1;
        if (ImGui::Selectable("UAID", sortMode == 2))
            sortMode = 2;

        ImGui::Checkbox("Ascending", &sortAscending);

        ImGui::Separator();
        ImGui::Text("Type Filters:");
        ImGui::Checkbox("Images", &showImages);
        ImGui::Checkbox("Audio", &showAudio);
        ImGui::Checkbox("Prefabs", &showPrefabs);
        ImGui::Checkbox("Fonts", &showFonts);

        ImGui::EndPopup();
    }

    ImGui::Spacing();
    char buffer[256] = {};
    strncpy(buffer, assetSearchQuery.c_str(), sizeof(buffer) - 1);
    ImGui::SetNextItemWidth(-1);
    if (ImGui::InputTextWithHint("##Search", "Search", buffer, sizeof(buffer)))
        assetSearchQuery = buffer;

    ImGui::Separator();
    ImGui::BeginChild("##AssetScroll", ImVec2(0, 0), true);

    float padding = 8.0f;
    float thumbnailSize = 64.0f;
    float cellSize = thumbnailSize + padding;
    float availWidth = ImGui::GetContentRegionAvail().x;
    int columns = static_cast<int>(availWidth / cellSize);
    if (columns < 1)
        columns = 1;
    ImGui::Columns(columns, nullptr, false);

    std::vector<const AssetInfo *> sortedAssets;
    for (const auto &[uaid, asset] : AssetManager::GetAllAssets())
    {
        if (!asset || !asset->loaded)
            continue;
        if (!assetSearchQuery.empty() &&
            asset->filename.find(assetSearchQuery) == std::string::npos &&
            asset->path.find(assetSearchQuery) == std::string::npos)
            continue;
        if ((asset->type == AssetType::Image && !showImages) ||
            (asset->type == AssetType::Prefab && !showPrefabs) ||
            (asset->type == AssetType::Font && !showFonts) ||
            (asset->type == AssetType::Audio && !showAudio))
            continue;
        sortedAssets.push_back(asset.get());
    }

    std::sort(sortedAssets.begin(), sortedAssets.end(), [](const AssetInfo *a, const AssetInfo *b)
              {
        switch (sortMode) {
            case 0: return sortAscending ? a->filename < b->filename : a->filename > b->filename;
            case 1: return sortAscending ? a->type < b->type : a->type > b->type;
            case 2: return sortAscending ? a->uaid < b->uaid : a->uaid > b->uaid;
            default: return true;
        } });

    int idx = 0;
    for (const AssetInfo *asset : sortedAssets)
    {
        ImGui::PushID(idx++);
        std::string rawDisplayName = GetFilenameFromPath(asset->path);

        std::string displayName = TruncateWithEllipsis(GetFilenameNoExtension(rawDisplayName), 10);

        if (asset->type == AssetType::Image)
        {
            const auto *image = dynamic_cast<const ImageAssetInfo *>(asset);
            if (!image)
            {
                ImGui::PopID();
                continue;
            }

            ImGui::Image((ImTextureID)(intptr_t)image->textureID, ImVec2(thumbnailSize, thumbnailSize));
            if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceAllowNullID))
            {
                ImGui::SetDragDropPayload(ASSET_TEXTURE, &asset->uaid, sizeof(uint64_t));
                ImGui::Text("%s", rawDisplayName.c_str());
                ImGui::EndDragDropSource();
            }
        }
        else if (asset->type == AssetType::Audio)
        {
            ImGui::Button(asset->filetype.empty() ? "Audio" : asset->filetype.c_str(), ImVec2(thumbnailSize, thumbnailSize));
            if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceAllowNullID))
            {
                ImGui::SetDragDropPayload(ASSET_AUDIO, &asset->uaid, sizeof(uint64_t));
                ImGui::Text("%s", rawDisplayName.c_str());
                ImGui::EndDragDropSource();
            }
        }
        else if (asset->type == AssetType::Font)
        {
            auto *fontInfo = static_cast<const FontAssetInfo *>(asset);

            // reserve a square region for our “ABC” preview
            ImGui::BeginGroup();
            ImGui::PushID((void *)(intptr_t)asset->uaid);

            ImVec2 iconSize(thumbnailSize, thumbnailSize);
            ImGui::InvisibleButton("FontPreview", iconSize);
            ImVec2 p0 = ImGui::GetItemRectMin();
            ImVec2 p1 = ImGui::GetItemRectMax();

            // compute atlas rows/cols
            const int cols = 16;
            const int count = 127 - 32;
            const int rows = (count + cols - 1) / cols;
            float invCols = 1.0f / float(cols);
            float invRows = 1.0f / float(rows);

            // size for each glyph in preview (3 across)
            ImVec2 glyphSize(iconSize.x / 3.0f, iconSize.y);

            // draw “A”, “B”, “C”
            ImDrawList *dl = ImGui::GetWindowDrawList();
            const char sample[] = {'A', 'B', 'C'};
            for (int i = 0; i < 3; ++i)
            {
                int idx = int(sample[i]) - 32;
                int cx = idx % cols, cy = idx / cols;

                ImVec2 uv0(cx * invCols, cy * invRows);
                ImVec2 uv1((cx + 1) * invCols, (cy + 1) * invRows);

                ImVec2 dst0(p0.x + i * glyphSize.x, p0.y);
                ImVec2 dst1(dst0.x + glyphSize.x, dst0.y + glyphSize.y);

                dl->AddImage(
                    (ImTextureID)(uintptr_t)fontInfo->atlasTextureID,
                    dst0, dst1,
                    uv0, uv1,
                    IM_COL32(255, 255, 255, 255));
            }

            // drag & drop
            if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceAllowNullID))
            {
                ImGui::SetDragDropPayload(ASSET_FONT, &asset->uaid, sizeof(UAssetID));
                ImGui::Text("%s", asset->filename.c_str());
                ImGui::EndDragDropSource();
            }

            ImGui::PopID();
            ImGui::EndGroup();
        }

        else if (asset->type == AssetType::Prefab)
        {
            const auto *prefab = dynamic_cast<const PrefabAssetInfo *>(asset);

            ImGui::Button("Prefab", ImVec2(thumbnailSize, thumbnailSize));
            if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceAllowNullID))
            {
                ImGui::SetDragDropPayload(ASSET_PREFAB, &prefab->uaid, sizeof(uint64_t));
                ImGui::Text("%s", rawDisplayName.c_str());
                ImGui::EndDragDropSource();
            }
        }
        else
        {
            ImGui::PopID();
            continue;
        }

        if (ImGui::IsItemHovered())
        {
            ImGui::BeginTooltip();
            ImGui::Text("Path: %s", asset->path.c_str());
            ImGui::Text("UAID: %llu", asset->uaid);
            if (asset->type == AssetType::Image)
            {
                auto *image = dynamic_cast<const ImageAssetInfo *>(asset);
                if (image)
                {
                    ImGui::Text("Texture ID: %u", image->textureID);
                    ImGui::Text("Size: (%.0f, %.0f)", image->size.x, image->size.y);
                }
            }
            ImGui::EndTooltip();
        }

        if (ImGui::BeginPopupContextItem("AssetContext"))
        {
            if (ImGui::MenuItem("Unload"))
            {
                AssetManager::UnloadAsset(asset->uaid);
                ImGui::EndPopup();
                ImGui::PopID();
                continue;
            }
            if (ImGui::MenuItem("Copy Path"))
                ImGui::SetClipboardText(asset->path.c_str());
            if (ImGui::MenuItem("Copy UAID"))
                ImGui::SetClipboardText(std::to_string(asset->uaid).c_str());
            ImGui::EndPopup();
        }

        ImGui::TextWrapped("%s", displayName.c_str());
        ImGui::NextColumn();
        ImGui::PopID();
    }

    ImGui::Columns(1);
    ImGui::EndChild();
    ImGui::End();

    if (ImGui::BeginPopupModal("Import Assets", nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize))
    {
        ImGui::TextWrapped("Confirm Imports");
        ImGui::Spacing();

        constexpr float tableWidth = 520.0f;
        if (ImGui::BeginTable("ImportTable", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable, ImVec2(tableWidth, 300)))
        {
            ImGui::TableSetupColumn("Filename", ImGuiTableColumnFlags_WidthStretch);
            ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthFixed, 120.0f);
            ImGui::TableHeadersRow();

            for (auto &[path, type] : pendingImports)
            {
                ImGui::TableNextRow();
                ImGui::TableSetColumnIndex(0);
                std::string filename = GetFilenameFromPath(path);
                ImGui::TextWrapped("%s", filename.c_str());

                ImGui::TableSetColumnIndex(1);
                const char *currentLabel =
                    type == AssetType::Image ? "Image" : type == AssetType::Audio ? "Audio"
                                                     : type == AssetType::Font    ? "Font"
                                                     : type == AssetType::Shader  ? "Shader"
                                                     : type == AssetType::Script  ? "Script"
                                                     : type == AssetType::Scene   ? "Scene"
                                                     : type == AssetType::Video   ? "Video"
                                                     : type == AssetType::Prefab  ? "Prefab"
                                                                                  : "Unknown";

                ImGui::SetNextItemWidth(-1);
                if (ImGui::BeginCombo(("##type_" + path).c_str(), currentLabel))
                {
                    if (ImGui::Selectable("Image", type == AssetType::Image))
                        type = AssetType::Image;
                    if (ImGui::Selectable("Audio", type == AssetType::Audio))
                        type = AssetType::Audio;
                    if (ImGui::Selectable("Font", type == AssetType::Font))
                        type = AssetType::Font;
                    if (ImGui::Selectable("Shader", type == AssetType::Shader))
                        type = AssetType::Shader;
                    if (ImGui::Selectable("Script", type == AssetType::Script))
                        type = AssetType::Script;
                    if (ImGui::Selectable("Scene", type == AssetType::Scene))
                        type = AssetType::Scene;
                    if (ImGui::Selectable("Video", type == AssetType::Video))
                        type = AssetType::Video;
                    if (ImGui::Selectable("Prefab", type == AssetType::Prefab))
                        type = AssetType::Prefab;
                    ImGui::EndCombo();
                }
            }

            ImGui::EndTable();
        }

        ImGui::Spacing();
        ImGui::Separator();
        ImGui::Spacing();

        float buttonWidth = 120.0f;
        float totalWidth = buttonWidth * 2 + ImGui::GetStyle().ItemSpacing.x;

        ImGui::SetCursorPosX((tableWidth - totalWidth) * 0.5f); // center buttons
        if (ImGui::Button("Import", ImVec2(buttonWidth, 0)))
        {
            LoadingWindow loader;
            loader.Create("Importing...");

            for (size_t i = 0; i < pendingImports.size(); ++i)
            {
                const auto &[path, type] = pendingImports[i];
                loader.Update("Importing", path, static_cast<float>(i + 1) / pendingImports.size());
                AssetManager::LoadAssetAsync(path, type);
            }

            loader.Destroy();
            pendingImports.clear();
            showImportPopup = false;
            ImGui::CloseCurrentPopup();
        }

        ImGui::SameLine();

        if (ImGui::Button("Cancel", ImVec2(buttonWidth, 0)))
        {
            pendingImports.clear();
            showImportPopup = false;
            ImGui::CloseCurrentPopup();
        }

        ImGui::EndPopup();
    }
}
