// DragonX Wallet - ImGui Edition
// Copyright 2024-2026 The Hush Developers
// Released under the GPLv3

#pragma once

#include <string>
#include <vector>
#include <cctype>
#include <cstring>
#include <cstddef>
#include "../../app.h"
#include "../../util/i18n.h"
#include "../../util/text_format.h"
#include "../material/draw_helpers.h"
#include "../material/project_icons.h"
#include "../theme.h"
#include "imgui.h"

namespace dragonx {
namespace ui {

class AddressLabelDialog {
public:
    static bool drawIconByName(ImDrawList* dl,
                               const std::string& name,
                               ImVec2 center,
                               float /*emSize*/,
                               ImU32 color,
                               ImFont* iconFont,
                               float iconFontSize) {
        return material::project_icons::drawByName(dl, name, center, color, iconFont, iconFontSize);
    }

    static void show(App* app, const std::string& address, bool isZ) {
        s_open = true;
        s_app = app;
        s_address = address;
        s_isZ = isZ;
        s_selectedIcon = -1;
        s_iconSearch[0] = '\0';

        // Pre-fill from existing metadata
        std::string existing = app->getAddressLabel(address);
        std::strncpy(s_label, existing.c_str(), sizeof(s_label) - 1);
        s_label[sizeof(s_label) - 1] = '\0';

        std::string existingIcon = app->getAddressIcon(address);
        for (int i = 0; i < material::project_icons::walletIconCount(); ++i) {
            if (material::project_icons::walletIconName(i) == existingIcon) {
                s_selectedIcon = i;
                break;
            }
        }
    }

    static void render() {
        if (!s_open || !s_app) return;

        using namespace material;

        constexpr float cardTopViewportRatio = 0.15f;
        constexpr float cardBottomViewportRatio = 0.80f;
        OverlayDialogSpec ov;
        ov.title = TR("set_label"); ov.p_open = &s_open;
        ov.style = OverlayStyle::BlurFloat;
        ov.cardWidth = 660.0f; ov.idSuffix = "addrlabel";
        ov.cardBottomViewportRatio = cardBottomViewportRatio;
        if (BeginOverlayDialog(ov)) {
            float dp = Layout::dpiScale();

            // Address preview
            Type().textColored(TypeStyle::Caption, OnSurfaceMedium(),
                s_isZ ? TR("shielded_address") : TR("transparent_address"));
            ImGui::Spacing();
            {
                std::string display = s_address;
                if (display.size() > 42) display = util::truncateMiddle(display, 20, 16);
                Type().textColored(TypeStyle::Caption, OnSurfaceDisabled(), display.c_str());
            }
            ImGui::Spacing();
            ImGui::Spacing();

            // Label input
            Type().text(TypeStyle::Subtitle2, TR("label"));
            ImGui::SetNextItemWidth(-1);
            ImGui::InputTextWithHint("##AddrLabel", TR("label_placeholder"), s_label, sizeof(s_label));
            ImGui::Spacing();
            ImGui::Spacing();

            // Icon picker grid
            Type().text(TypeStyle::Subtitle2, TR("choose_icon"));
            ImGui::Spacing();

            // Search bar
            ImGui::SetNextItemWidth(-1);
            ImGui::InputTextWithHint("##IconSearch", TR("search_icons"), s_iconSearch, sizeof(s_iconSearch));
            ImGui::Spacing();

            ImFont* iconFont = Type().iconMed();
            float iconFsz = ScaledFontSize(iconFont);
            float cellSz = iconFsz + 16.0f * dp;
            float avail = ImGui::GetContentRegionAvail().x;
            int cols = std::max(1, (int)(avail / (cellSz + 4.0f * dp)));

            const char* cancelLabel = TR("cancel");
            const char* saveLabel = TR("save");
            ImFont* buttonFont = Type().button();
            float buttonFontSize = ScaledFontSize(buttonFont);
            const ImGuiStyle& style = ImGui::GetStyle();
            const float cardHeight = ImGui::GetMainViewport()->Size.y * (cardBottomViewportRatio - cardTopViewportRatio);
            const float bottomPadding = style.WindowPadding.y;
            const bool showClearIcon = (s_selectedIcon >= 0);
            const float clearRowH = showClearIcon ? ImGui::GetTextLineHeight() : 0.0f;
            const float buttonRowH = ImGui::GetFrameHeight();
            const float separatorH = 0.0f;   // footer divider removed (reference design)
            const float preButtonReserve =
                (showClearIcon ? (style.ItemSpacing.y + clearRowH) : 0.0f) +
                style.ItemSpacing.y * 3.0f + separatorH;
            const float buttonY = cardHeight - bottomPadding - buttonRowH;

            // Build filtered index list
            std::vector<int> visible;
            visible.reserve(material::project_icons::walletIconCount());
            {
                // Simple case-insensitive substring match on icon name
                std::string needle(s_iconSearch);
                for (char& c : needle) c = (char)std::tolower((unsigned char)c);
                for (int i = 0; i < material::project_icons::walletIconCount(); ++i) {
                    const char* iconName = material::project_icons::walletIconName(i);
                    if (needle.empty() || std::strstr(iconName, needle.c_str()) != nullptr)
                        visible.push_back(i);
                }
            }

            // The grid owns all vertical space above the bottom action band.
            const float gridStartY = ImGui::GetCursorPosY();
            const float controlsTopY = std::max(gridStartY + cellSz * 2.0f, buttonY - preButtonReserve);
            const float gridMaxH = std::max(cellSz * 2.0f, controlsTopY - gridStartY);
            ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(0, 0, 0, 0));
            ImGui::PushStyleVar(ImGuiStyleVar_ScrollbarSize, 11.0f * dp);
            ImGui::PushStyleVar(ImGuiStyleVar_ScrollbarRounding, 5.5f * dp);
            // Scrollbar visible (not NoScrollbar) — the icon set exceeds the fixed-height
            // grid, so a real scrollbar is the discoverable way to reach the rest.
            ImGui::BeginChild("##IconGrid", ImVec2(avail, gridMaxH), ImGuiChildFlags_None,
                ImGuiWindowFlags_NoScrollWithMouse);
            ApplySmoothScroll();

            ImDrawList* dl = ImGui::GetWindowDrawList();

            if (visible.empty()) {
                Type().textColored(TypeStyle::Caption, OnSurfaceDisabled(), TR("no_icons_found"));
            }

            int col = 0;
            for (int vi = 0; vi < (int)visible.size(); ++vi) {
                int i = visible[vi];
                const char* iconName = material::project_icons::walletIconName(i);
                if (col != 0) ImGui::SameLine(0, 4.0f * dp);
                ImVec2 pos = ImGui::GetCursorScreenPos();
                ImVec2 mn = pos;
                ImVec2 mx(pos.x + cellSz, pos.y + cellSz);
                bool hov = ImGui::IsMouseHoveringRect(mn, mx);
                bool sel = (s_selectedIcon == i);

                // Background
                if (sel) {
                    dl->AddRectFilled(mn, mx, WithAlpha(Primary(), 40), 6.0f * dp);
                    dl->AddRect(mn, mx, WithAlpha(Primary(), 120), 6.0f * dp, 0, 1.5f * dp);
                } else if (hov) {
                    dl->AddRectFilled(mn, mx, IM_COL32(255, 255, 255, 20), 6.0f * dp);
                }

                // Icon centered in cell
                drawIconByName(dl,
                               iconName,
                               ImVec2(mn.x + cellSz * 0.5f, mn.y + cellSz * 0.5f),
                               iconFsz,
                               sel ? Primary() : (hov ? OnSurface() : OnSurfaceMedium()),
                               iconFont,
                               iconFsz);

                ImGui::PushID(i);
                ImGui::InvisibleButton("##icon", ImVec2(cellSz, cellSz));
                if (ImGui::IsItemClicked()) s_selectedIcon = i;
                if (hov) material::Tooltip("%s", iconName);
                ImGui::PopID();

                col = (col + 1) % cols;
            }

            ImGui::EndChild();
            ImGui::PopStyleVar(2);   // ScrollbarSize + ScrollbarRounding
            ImGui::PopStyleColor();

            if (ImGui::GetCursorPosY() < controlsTopY) {
                ImGui::SetCursorPosY(controlsTopY);
            }

            // "No icon" option
            if (showClearIcon) {
                ImGui::Spacing();
                if (material::TactileSmallButton(TR("clear_icon"))) {
                    s_selectedIcon = -1;
                }
            }

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

            if (ImGui::GetCursorPosY() < buttonY) {
                ImGui::SetCursorPosY(buttonY);
            }

            // Buttons
            float minBtnW = 120.0f * dp;
            float buttonPadW = ImGui::GetStyle().FramePadding.x * 2.0f + 24.0f * dp;
            float cancelW = std::max(minBtnW,
                buttonFont->CalcTextSizeA(buttonFontSize, 1000.0f, 0.0f, cancelLabel).x + buttonPadW);
            float saveW = std::max(minBtnW,
                buttonFont->CalcTextSizeA(buttonFontSize, 1000.0f, 0.0f, saveLabel).x + buttonPadW);
            float totalW = cancelW + saveW + Layout::spacingMd();
            float rowStartX = ImGui::GetCursorPosX();
            float contentW = ImGui::GetContentRegionAvail().x;
            ImGui::SetCursorPosX(rowStartX + std::max(0.0f, (contentW - totalW) * 0.5f));

            if (TactileButton(cancelLabel, ImVec2(cancelW, 0), buttonFont)) {
                s_open = false;
            }
            ImGui::SameLine(0, Layout::spacingMd());
            if (TactileButton(saveLabel, ImVec2(saveW, 0), buttonFont)) {
                // Apply changes
                // Trim surrounding whitespace; a whitespace-only label clears it
                // (mirroring how an empty icon selection clears the icon).
                std::string trimmedLabel(s_label);
                {
                    std::size_t b = trimmedLabel.find_first_not_of(" \t\r\n");
                    if (b == std::string::npos) {
                        trimmedLabel.clear();
                    } else {
                        std::size_t e = trimmedLabel.find_last_not_of(" \t\r\n");
                        trimmedLabel = trimmedLabel.substr(b, e - b + 1);
                    }
                }
                s_app->setAddressLabel(s_address, trimmedLabel);
                if (s_selectedIcon >= 0)
                    s_app->setAddressIcon(s_address, material::project_icons::walletIconName(s_selectedIcon));
                else
                    s_app->setAddressIcon(s_address, "");
                s_open = false;
            }

            EndOverlayDialog();
        }
    }

    static bool isOpen() { return s_open; }

    // Close the dialog (used by the UI sweep teardown).
    static void hide() { s_open = false; }

private:
    static inline bool s_open = false;
    static inline App* s_app = nullptr;
    static inline std::string s_address;
    static inline bool s_isZ = false;
    static inline char s_label[128] = {};
    static inline int s_selectedIcon = -1;
    static inline char s_iconSearch[64] = {};

public:
    // Expose for the address list to look up icon glyphs by name
    static const char* iconGlyphForName(const std::string& name) {
        return material::project_icons::glyphForName(name);
    }
};

} // namespace ui
} // namespace dragonx
