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

#include "faq_dialog.h"
#include "faq_content.h"
#include "../../app.h"
#include "../../util/i18n.h"
#include "../../util/text_format.h"
#include "../../embedded/IconsMaterialDesign.h"
#include "../schema/ui_schema.h"
#include "../layout.h"
#include "../material/type.h"
#include "../material/colors.h"
#include "../material/draw_helpers.h"
#include "imgui.h"

#include <algorithm>
#include <string>
#include <unordered_map>
#include <vector>

namespace dragonx {
namespace ui {

namespace {

// Persists across frames (the dialog is re-entered each frame while open). Group 0 = Wallet,
// 1 = Daemon. `expanded` keys are FaqEntry::questionKey (stable string literals from faq_content).
struct FaqDialogState {
    int  group = 0;
    char search[128] = "";
    std::unordered_map<std::string, bool> expanded;
};
FaqDialogState s_faq;

bool entryMatches(const faq::FaqEntry& e, const char* query)
{
    return util::containsIgnoreCase(TR(e.questionKey), query) ||
           util::containsIgnoreCase(TR(e.answerKey), query);
}

// One answer body: wrapped, muted. Shared by the collapsible (non-search) and search paths.
void renderAnswer(const char* answerKey)
{
    ImGui::Indent(Layout::spacingMd());
    ImGui::PushFont(material::Type().body2());
    ImGui::PushStyleColor(ImGuiCol_Text, ImGui::ColorConvertU32ToFloat4(material::OnSurfaceMedium()));
    ImGui::TextWrapped("%s", TR(answerKey));
    ImGui::PopStyleColor();
    ImGui::PopFont();
    ImGui::Unindent(Layout::spacingMd());
    ImGui::Dummy(ImVec2(0, Layout::spacingSm()));
}

} // namespace

void RenderFaqDialog(App* app, bool* p_open)
{
    auto& S = schema::UI();
    auto win = S.window("dialogs.faq");
    const float dp = Layout::dpiScale();

    const bool daemonAvailable = app && app->supportsFullNodeLifecycleActions();
    if (!daemonAvailable) s_faq.group = 0;   // no Daemon tab in lite builds

    // Floating "BlurFloat" modal, matching the Wallets dialog: live-blur backdrop, no boxed card, a
    // plain heading (no ✕ — a Close button sits at the bottom). Roomy fixed width; height capped to the
    // viewport so the content flexes + scrolls on small / HiDPI screens.
    const float vpH   = ImGui::GetMainViewport()->Size.y;
    const float wantH = (win.height > 0 ? win.height : 640.0f) * dp;
    material::OverlayDialogSpec spec;
    spec.title      = TR("faq_title");
    spec.p_open     = p_open;
    spec.style      = material::OverlayStyle::BlurFloat;
    spec.cardWidth  = (win.width  > 0 ? win.width  : 860.0f);
    spec.cardHeight = std::min(wantH, vpH * 0.86f) / dp;
    spec.idSuffix   = "faq";
    if (!material::BeginOverlayDialog(spec)) {
        return;
    }
    // Esc closes (ImGui consumes Esc itself while the search box is being edited, so this only
    // fires when the field isn't capturing it).
    if (ImGui::IsKeyPressed(ImGuiKey_Escape)) *p_open = false;

    // Subtitle under the plain heading, matching the Wallets dialog's intro caption.
    material::Type().textColored(material::TypeStyle::Caption, material::OnSurfaceMedium(),
                                 TR(daemonAvailable ? "faq_intro" : "faq_intro_lite"));
    ImGui::Dummy(ImVec2(0, Layout::spacingSm()));

    const float contentW = ImGui::GetContentRegionAvail().x;

    // ── Group tabs: Wallet | Daemon — only when there's a choice. Lite has just the Wallet group, so a
    // lone "Wallet" selector is redundant; skip it entirely (the group is already pinned to 0 above).
    if (daemonAvailable) {
        const float gap = ImGui::GetStyle().ItemSpacing.x;
        const float tabW = (contentW - gap) / 2.0f;
        auto tab = [&](const char* label, int idx) {
            const bool active = (s_faq.group == idx);
            if (active) {
                ImGui::PushStyleColor(ImGuiCol_Button, ImGui::ColorConvertU32ToFloat4(material::Primary()));
                ImGui::PushStyleColor(ImGuiCol_Text,   ImGui::ColorConvertU32ToFloat4(material::OnPrimary()));
            }
            if (material::TactileButton(label, ImVec2(tabW, 0))) s_faq.group = idx;
            if (active) ImGui::PopStyleColor(2);
        };
        tab(TR("faq_group_wallet"), 0);
        ImGui::SameLine();
        tab(TR("faq_group_daemon"), 1);
    }

    ImGui::Dummy(ImVec2(0, Layout::spacingXs()));

    // ── Search ──
    ImGui::SetNextItemWidth(contentW);
    ImGui::InputTextWithHint("##FaqSearch", TR("faq_search_hint"), s_faq.search, sizeof(s_faq.search));
    const bool searching = s_faq.search[0] != '\0';

    ImGui::Dummy(ImVec2(0, Layout::spacingSm()));

    // ── Scrollable Q&A body ── (reserve room for the Close button footer below)
    const float footerH = ImGui::GetFrameHeightWithSpacing() + Layout::spacingMd();
    float bodyH = ImGui::GetContentRegionAvail().y - footerH;
    if (bodyH < 80.0f * dp) bodyH = 80.0f * dp;
    // Inner padding gives the content breathing room and, on the right, a clear gap to the LEFT of the
    // scrollbar (WindowPadding.x is exactly that gap); the scrollbar itself is made chunkier than the
    // app default. NoScrollWithMouse + ApplySmoothScroll gives the wheel eased scrolling, matching the
    // Wallets dialog / Settings page (ApplySmoothScroll owns the wheel input and lerps ScrollY).
    ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(Layout::spacingMd(), Layout::spacingXs()));
    ImGui::PushStyleVar(ImGuiStyleVar_ScrollbarSize, 16.0f * dp);
    ImGui::BeginChild("##FaqScroll", ImVec2(0, bodyH), false,
                      ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollWithMouse);
    material::ApplySmoothScroll();
    ImDrawList* dl = ImGui::GetWindowDrawList();

    const auto& groups = (s_faq.group == 1 && daemonAvailable) ? faq::daemonFaq() : faq::walletFaq(daemonAvailable);
    bool anyShown = false;

    bool firstSection = true;
    for (const auto& subcat : groups) {
        // Collect the entries visible under the current search.
        std::vector<const faq::FaqEntry*> visible;
        for (const auto& e : subcat.entries) {
            if (!searching || entryMatches(e, s_faq.search)) visible.push_back(&e);
        }
        if (visible.empty()) continue;

        // Section break: generous space above every section after the first, so topic groups read as
        // clearly separated bands rather than one uniform list.
        if (!firstSection) ImGui::Dummy(ImVec2(0, Layout::spacingLg()));
        firstSection = false;
        anyShown = true;

        // Section header — accent overline + a thin full-width rule beneath it, anchoring the group
        // above its (brighter, normal-case) question rows.
        material::Type().textColored(material::TypeStyle::Overline,
                                     material::Primary(), TR(subcat.titleKey));
        {
            const ImVec2 rp = ImGui::GetCursorScreenPos();
            const float  rw = ImGui::GetContentRegionAvail().x;
            dl->AddLine(ImVec2(rp.x, rp.y + dp), ImVec2(rp.x + rw, rp.y + dp),
                        material::Divider(), 1.0f * dp);
        }
        ImGui::Dummy(ImVec2(0, Layout::spacingSm()));

        for (const auto* e : visible) {
            const float rowW = ImGui::GetContentRegionAvail().x;
            if (searching) {
                // Search results: show question + answer directly (no collapsing).
                ImGui::PushFont(material::Type().subtitle2());
                ImGui::TextWrapped("%s", TR(e->questionKey));
                ImGui::PopFont();
                renderAnswer(e->answerKey);
            } else {
                bool& exp = s_faq.expanded[e->questionKey];
                std::string id = std::string("##faq_") + e->questionKey;
                material::CollapsibleHeader(dl, id.c_str(), TR(e->questionKey), exp, rowW,
                                            material::Type().subtitle2(), material::OnSurface());
                if (exp) renderAnswer(e->answerKey);
            }
        }
    }

    if (!anyShown) {
        ImGui::Dummy(ImVec2(0, Layout::spacingLg()));
        ImGui::PushStyleColor(ImGuiCol_Text, ImGui::ColorConvertU32ToFloat4(material::OnSurfaceMedium()));
        ImGui::TextWrapped("%s", TR("faq_no_results"));
        ImGui::PopStyleColor();
    }

    ImGui::EndChild();
    ImGui::PopStyleVar(2);   // ScrollbarSize, WindowPadding

    // Close button footer (BlurFloat has no ✕ in the heading).
    const float closeW = 120.0f * dp;
    material::BeginOverlayDialogFooter(closeW, false);
    if (material::TactileButton(TR("close"), ImVec2(closeW, 0))) *p_open = false;

    material::EndOverlayDialog();
}

} // namespace ui
} // namespace dragonx
