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

#pragma once

#include <string>
#include <memory>
#include "../../app.h"
#include "../../util/bootstrap.h"
#include "../../util/platform.h"
#include "../../util/i18n.h"
#include "../material/draw_helpers.h"
#include "../material/type.h"
#include "../material/colors.h"
#include "../theme.h"
#include "../../embedded/IconsMaterialDesign.h"
#include "imgui.h"

namespace dragonx {
namespace ui {

/**
 * @brief Modal dialog for downloading blockchain bootstrap from Settings.
 *
 * Reuses the existing Bootstrap class for download/verify/extract.
 * States: Confirm → Downloading → Done / Failed
 */
class BootstrapDownloadDialog {
public:
    static void show(App* app) {
        if (!app || !app->supportsFullNodeLifecycleActions()) return;
        s_app = app;
        // If a download is already in flight, RE-ATTACH to it (just reopen showing progress) instead of
        // resetting state and orphaning the running worker / restarting an unverified download.
        if (app->isBootstrapDownloading()) {
            s_open = true;
            if (s_state == State::Confirm) s_state = State::Downloading;
            return;
        }
        s_open = true;
        s_state = State::Confirm;
        s_bootstrap.reset();
        s_errorMsg.clear();
        s_wasDaemonRunning = false;
    }

    static bool isOpen() { return s_open; }

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

    static void render() {
        if (!s_app) return;
        if (!s_open) {
            // Dialog was closed — ensure flag is cleared
            if (s_app->isBootstrapDownloading() && s_state != State::Downloading) {
                s_app->setBootstrapDownloading(false);
            }
            return;
        }

        using namespace material;
        const float dp = Layout::dpiScale();

        OverlayDialogSpec ov;
        ov.title = TR("download_bootstrap"); ov.p_open = &s_open;
        ov.style = OverlayStyle::BlurFloat; ov.cardWidth = 500.0f; ov.cardBottomViewportRatio = 0.94f;
        if (BeginOverlayDialog(ov)) {

            if (s_state == State::Confirm) {
                renderConfirm(dp);
            } else if (s_state == State::Downloading) {
                renderProgress(dp);
            } else if (s_state == State::Done) {
                renderDone(dp);
            } else if (s_state == State::Failed) {
                renderFailed(dp);
            }

            EndOverlayDialog();
        }
    }

private:
    enum class State { Confirm, Downloading, Done, Failed };

    // ---- Confirm screen ----
    static void renderConfirm(float dp) {
        using namespace material;
        ImGui::Spacing();

        // Description
        ImGui::TextWrapped("%s", TR("bootstrap_desc"));
        ImGui::Spacing();

        // Care header (reference style: ⚠ + Warning color, wraps if long).
        DialogWarningHeader(TR("bootstrap_warning"));

        ImGui::Spacing();

        // Trust warning
        {
            ImFont* iconFont = Type().iconSmall();
            ImGui::PushFont(iconFont);
            ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(OnSurfaceDisabled()), "%s", ICON_MD_VERIFIED_USER);
            ImGui::PopFont();
            ImGui::SameLine();
            ImGui::PushStyleColor(ImGuiCol_Text, ImGui::ColorConvertU32ToFloat4(OnSurfaceMedium()));
            ImGui::TextWrapped("%s", TR("bootstrap_trust_warning"));
            ImGui::PopStyleColor();
        }

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

        // Buttons: Download | Mirror | Cancel — centered as a group.
        float btnW = 140.0f * dp;
        float btnSm = 90.0f * dp;
        const float rowTotal = btnW * 2.0f + btnSm + ImGui::GetStyle().ItemSpacing.x * 2.0f;
        const float rowOff = (ImGui::GetContentRegionAvail().x - rowTotal) * 0.5f;
        if (rowOff > 0.0f) ImGui::SetCursorPosX(ImGui::GetCursorPosX() + rowOff);

        if (TactileButton(TR("download"), ImVec2(btnW, 0))) {
            startDownload("");
        }
        ImGui::SameLine();
        if (TactileButton(TR("bootstrap_mirror"), ImVec2(btnW, 0))) {
            std::string mirrorUrl = std::string(util::Bootstrap::kMirrorUrl) + "/" + util::Bootstrap::kZipName;
            startDownload(mirrorUrl);
        }
        if (ImGui::IsItemHovered()) {
            material::Tooltip("%s", TR("bootstrap_mirror_tooltip"));
        }
        ImGui::SameLine();
        if (TactileButton(TR("cancel"), ImVec2(btnSm, 0))) {
            s_open = false;
        }
    }

    // ---- Progress screen ----
    static void renderProgress(float dp) {
        using namespace material;

        if (!s_bootstrap) {
            s_state = State::Failed;
            s_errorMsg = TR("grpc_bootstrap_not_initialized");
            return;
        }

        auto prog = s_bootstrap->getProgress();

        // Status title
        const char* statusTitle;
        if (prog.state == util::Bootstrap::State::Downloading)
            statusTitle = TR("bootstrap_downloading");
        else if (prog.state == util::Bootstrap::State::Verifying)
            statusTitle = TR("bootstrap_verifying");
        else
            statusTitle = TR("bootstrap_extracting");
        Type().text(TypeStyle::Subtitle2, statusTitle);
        ImGui::Spacing();

        // Progress bar
        material::ProgressBar(ImGui::GetContentRegionAvail().x, 8.0f * dp, prog.percent / 100.0f);
        ImGui::Spacing();

        // Percent + status text
        {
            char pctBuf[32];
            snprintf(pctBuf, sizeof(pctBuf), "%.1f%%", prog.percent);
            float pctW = ImGui::CalcTextSize(pctBuf).x;
            ImGui::Text("%s", prog.status_text.c_str());
            ImGui::SameLine(ImGui::GetContentRegionAvail().x - pctW + ImGui::GetCursorPosX());
            ImGui::Text("%s", pctBuf);
        }

        // wallet.dat protection notice during extraction
        if (prog.state == util::Bootstrap::State::Extracting) {
            Type().textColored(TypeStyle::Caption, OnSurfaceMedium(), TR("bootstrap_wallet_protected"));
        }

        ImGui::Spacing();

        // Daemon status indicator
        {
            bool daemonUp = s_app->isEmbeddedDaemonRunning();
            const std::string& dStatus = s_app->getDaemonStatus();
            ImU32 dotCol = daemonUp ? IM_COL32(76, 175, 80, 200)
                                    : IM_COL32(120, 120, 120, 160);
            if (dStatus.find("Stopping") != std::string::npos)
                dotCol = IM_COL32(255, 167, 38, 200);
            const char* label = daemonUp ? (dStatus.find("Stopping") != std::string::npos
                                           ? TR("bootstrap_daemon_stopping")
                                           : TR("bootstrap_daemon_running"))
                                        : TR("bootstrap_daemon_stopped");

            ImDrawList* ddl = ImGui::GetWindowDrawList();
            float dotR = 3.5f * dp;
            ImVec2 cp = ImGui::GetCursorScreenPos();
            ddl->AddCircleFilled(ImVec2(cp.x + dotR, cp.y + ImGui::GetTextLineHeight() * 0.5f),
                                 dotR, dotCol);
            ImGui::Indent(dotR * 2.0f + 6.0f * dp);
            Type().textColored(TypeStyle::Caption, OnSurfaceDisabled(), label);
            ImGui::Unindent(dotR * 2.0f + 6.0f * dp);
        }

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

        // Cancel button — once clicked, disable it so the request is visibly
        // acknowledged (and can't be re-fired) until the worker actually stops.
        float btnW = 100.0f * dp;
        ImGui::BeginDisabled(s_cancelling);
        if (TactileButton(TR("cancel"), ImVec2(btnW, 0))) {
            s_cancelling = true;
            s_bootstrap->cancel();
        }
        ImGui::EndDisabled();

        // Check completion
        if (s_bootstrap->isDone()) {
            auto finalProg = s_bootstrap->getProgress();
            if (finalProg.state == util::Bootstrap::State::Completed) {
                // Reconcile the preserved wallet.dat against the new chain once the daemon is back up.
                s_app->markPostBootstrapRescanPending();
                s_state = State::Done;
            } else {
                s_errorMsg = finalProg.error;
                if (s_errorMsg.empty()) s_errorMsg = TR("grpc_bootstrap_failed");
                s_state = State::Failed;
            }
            s_bootstrap.reset();
            s_cancelling = false;
        }
    }

    // ---- Done screen ----
    static void renderDone(float dp) {
        using namespace material;
        ImGui::Spacing();

        Type().textColored(TypeStyle::H6, Success(), TR("bootstrap_success"));
        ImGui::Spacing();
        ImGui::TextWrapped("%s", TR("bootstrap_success_desc"));
        ImGui::Spacing();
        ImGui::Spacing();

        float btnW = 140.0f * dp;
        if (s_wasDaemonRunning) {
            if (TactileButton(TR("bootstrap_restart_daemon"), ImVec2(btnW, 0))) {
                s_app->setBootstrapDownloading(false);
                s_app->startEmbeddedDaemon();
                s_open = false;
            }
            ImGui::SameLine();
        }
        if (TactileButton(TR("close"), ImVec2(90.0f * dp, 0))) {
            s_app->setBootstrapDownloading(false);
            s_open = false;
        }
    }

    // ---- Failed screen ----
    static void renderFailed(float dp) {
        using namespace material;
        ImGui::Spacing();

        Type().textColored(TypeStyle::H6, Error(), TR("bootstrap_failed"));
        ImGui::Spacing();
        ImGui::TextWrapped("%s", s_errorMsg.c_str());
        ImGui::Spacing();
        ImGui::Spacing();

        float btnW = 120.0f * dp;
        if (TactileButton(TR("retry"), ImVec2(btnW, 0))) {
            startDownload("");
        }
        ImGui::SameLine();
        if (TactileButton(TR("close"), ImVec2(90.0f * dp, 0))) {
            s_app->setBootstrapDownloading(false);
            s_open = false;
        }
    }

    // ---- Shared: kick off download ----
    static void startDownload(const std::string& url) {
        if (!s_app || !s_app->supportsFullNodeLifecycleActions()) return;
        s_wasDaemonRunning = s_app->stopDaemonForBootstrap();
        s_app->setBootstrapDownloading(true);
        s_bootstrap = std::make_unique<util::Bootstrap>();
        std::string dataDir = util::Platform::getDragonXDataDir();
        if (url.empty())
            s_bootstrap->start(dataDir);
        else
            s_bootstrap->start(dataDir, url);
        s_state = State::Downloading;
        s_errorMsg.clear();
        s_cancelling = false;
    }

    static inline bool s_open = false;
    static inline App* s_app = nullptr;
    static inline State s_state = State::Confirm;
    static inline std::unique_ptr<util::Bootstrap> s_bootstrap;
    static inline bool s_wasDaemonRunning = false;
    static inline bool s_cancelling = false;  // cancel requested; disables the Cancel button until the worker stops
    static inline std::string s_errorMsg;
};

} // namespace ui
} // namespace dragonx
