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

#pragma once

#include "../colors.h"
#include "../typography.h"
#include "../layout.h"
#include "../../schema/ui_schema.h"
#include "imgui.h"
#include "imgui_internal.h"

namespace dragonx {
namespace ui {
namespace material {

// ============================================================================
// Material Design Navigation Drawer Component
// ============================================================================
// Based on https://m2.material.io/components/navigation-drawer
//
// Navigation drawers provide access to destinations in your app.

enum class NavDrawerType {
    Standard,      // Permanent, always visible
    Modal,         // Overlay with scrim, can be dismissed
    Dismissible    // Can be shown/hidden, no scrim
};

/**
 * @brief Navigation drawer configuration
 */
struct NavDrawerSpec {
    NavDrawerType type = NavDrawerType::Standard;
    float width = 256.0f;              // 256dp standard width
    bool showDividerBottom = true;     // Divider at bottom
    const char* headerTitle = nullptr;  // Optional header title
    const char* headerSubtitle = nullptr;
};

/**
 * @brief Navigation item configuration
 */
struct NavItemSpec {
    const char* icon = nullptr;        // Leading icon
    const char* label = nullptr;       // Item label (required)
    bool selected = false;             // Selected state
    bool disabled = false;
    int badgeCount = 0;               // Badge (0 = no badge)
};

/**
 * @brief Begin a navigation drawer
 * 
 * @param id Unique identifier
 * @param open Pointer to open state (for modal/dismissible)
 * @param spec Drawer configuration
 * @return true if drawer is visible
 */
bool BeginNavDrawer(const char* id, bool* open, const NavDrawerSpec& spec = NavDrawerSpec());

/**
 * @brief Begin standard (always visible) navigation drawer
 */
bool BeginNavDrawer(const char* id, const NavDrawerSpec& spec = NavDrawerSpec());

/**
 * @brief End navigation drawer
 */
void EndNavDrawer();

/**
 * @brief Render a navigation item
 * 
 * @param spec Item configuration
 * @return true if clicked
 */
bool NavItem(const NavItemSpec& spec);

/**
 * @brief Simple navigation item
 */
bool NavItem(const char* icon, const char* label, bool selected = false);

/**
 * @brief Navigation divider
 */
void NavDivider();

/**
 * @brief Navigation subheader
 */
void NavSubheader(const char* text);

// ============================================================================
// Implementation
// ============================================================================

struct NavDrawerState {
    float width;
    ImVec2 contentMin;
    ImVec2 contentMax;
    bool isModal;
};

static NavDrawerState g_navDrawerState;

inline bool BeginNavDrawer(const char* id, bool* open, const NavDrawerSpec& spec) {
    // For modal drawers, check open state
    if (spec.type == NavDrawerType::Modal && !*open) {
        return false;
    }
    
    ImGuiWindow* window = ImGui::GetCurrentWindow();
    if (window->SkipItems)
        return false;
    
    ImGui::PushID(id);
    
    g_navDrawerState.width = spec.width;
    g_navDrawerState.isModal = (spec.type == NavDrawerType::Modal);
    
    ImGuiIO& io = ImGui::GetIO();
    ImDrawList* drawList = window->DrawList;
    
    // For modal, draw scrim and handle dismiss
    if (spec.type == NavDrawerType::Modal) {
        ImDrawList* bgDrawList = ImGui::GetBackgroundDrawList();
        bgDrawList->AddRectFilled(
            ImVec2(0, 0), io.DisplaySize,
            schema::UI().resolveColor("var(--scrim)", IM_COL32(0, 0, 0, (int)(0.32f * 255)))
        );
        
        // Click outside to dismiss
        if (ImGui::IsMouseClicked(0)) {
            ImVec2 mousePos = io.MousePos;
            if (mousePos.x > spec.width) {
                *open = false;
            }
        }
    }
    
    // Drawer position and size
    ImVec2 drawerPos(0, 0);
    ImVec2 drawerSize(spec.width, io.DisplaySize.y);
    
    // If not modal, account for app bar
    if (spec.type != NavDrawerType::Modal) {
        drawerPos.y = size::AppBarHeight;
        drawerSize.y = io.DisplaySize.y - size::AppBarHeight;
    }
    
    ImRect drawerBB(drawerPos, ImVec2(drawerPos.x + drawerSize.x, drawerPos.y + drawerSize.y));
    
    // Draw drawer background
    ImU32 bgColor = Surface(Elevation::Dp16);
    drawList->AddRectFilled(drawerBB.Min, drawerBB.Max, bgColor);
    
    // Store content region
    g_navDrawerState.contentMin = ImVec2(drawerBB.Min.x, drawerBB.Min.y);
    g_navDrawerState.contentMax = drawerBB.Max;
    
    // Header
    float currentY = drawerBB.Min.y;
    
    if (spec.headerTitle || spec.headerSubtitle) {
        // Header area (optional)
        float headerHeight = 64.0f;
        
        ImVec2 headerMin(drawerBB.Min.x, currentY);
        ImVec2 headerMax(drawerBB.Max.x, currentY + headerHeight);
        
        // Header background (slightly elevated)
        drawList->AddRectFilled(headerMin, headerMax, Surface(Elevation::Dp16));
        
        // Header title
        if (spec.headerTitle) {
            ImGui::SetCursorScreenPos(ImVec2(drawerBB.Min.x + spacing::dp(2), currentY + 20.0f));
            Typography::instance().text(TypeStyle::H6, spec.headerTitle);
        }
        
        if (spec.headerSubtitle) {
            ImGui::SetCursorScreenPos(ImVec2(drawerBB.Min.x + spacing::dp(2), currentY + 42.0f));
            Typography::instance().textColored(TypeStyle::Body2, OnSurfaceMedium(), spec.headerSubtitle);
        }
        
        currentY += headerHeight;
        
        // Divider under header
        drawList->AddLine(
            ImVec2(drawerBB.Min.x, currentY),
            ImVec2(drawerBB.Max.x, currentY),
            OnSurfaceDisabled()
        );
    }
    
    // Set cursor for nav items
    ImGui::SetCursorScreenPos(ImVec2(drawerBB.Min.x, currentY + spacing::dp(1)));
    ImGui::BeginGroup();
    
    return true;
}

inline bool BeginNavDrawer(const char* id, const NavDrawerSpec& spec) {
    static bool alwaysOpen = true;
    NavDrawerSpec standardSpec = spec;
    standardSpec.type = NavDrawerType::Standard;
    return BeginNavDrawer(id, &alwaysOpen, standardSpec);
}

inline void EndNavDrawer() {
    ImGui::EndGroup();
    
    // Divider at bottom if configured
    ImGuiWindow* window = ImGui::GetCurrentWindow();
    ImDrawList* drawList = window->DrawList;
    
    // Right edge divider
    drawList->AddLine(
        ImVec2(g_navDrawerState.contentMax.x - 1, g_navDrawerState.contentMin.y),
        ImVec2(g_navDrawerState.contentMax.x - 1, g_navDrawerState.contentMax.y),
        OnSurfaceDisabled()
    );
    
    ImGui::PopID();
}

inline bool NavItem(const NavItemSpec& spec) {
    ImGuiWindow* window = ImGui::GetCurrentWindow();
    if (window->SkipItems)
        return false;
    
    ImGui::PushID(spec.label);
    
    // Item dimensions
    const float itemHeight = 48.0f;
    const float iconSize = 24.0f;
    const float horizontalPadding = spacing::dp(2);  // 16dp
    const float iconLabelGap = spacing::dp(4);       // 32dp from left edge to label
    
    float itemWidth = g_navDrawerState.width - spacing::dp(1);  // 8dp margin right
    
    ImVec2 pos = window->DC.CursorPos;
    pos.x += spacing::dp(1);  // 8dp margin left
    
    ImRect itemBB(pos, ImVec2(pos.x + itemWidth, pos.y + itemHeight));
    
    // Interaction
    ImGuiID id = window->GetID("##navitem");
    ImGui::ItemSize(ImRect(window->DC.CursorPos, ImVec2(window->DC.CursorPos.x + g_navDrawerState.width, window->DC.CursorPos.y + itemHeight)));
    if (!ImGui::ItemAdd(itemBB, id))
        return false;
    
    bool hovered, held;
    bool pressed = ImGui::ButtonBehavior(itemBB, id, &hovered, &held) && !spec.disabled;
    
    // Draw background
    ImDrawList* drawList = window->DrawList;
    
    ImU32 bgColor = 0;
    if (spec.selected) {
        bgColor = WithAlpha(Primary(), 30);  // Primary at ~12%
    } else if (held && !spec.disabled) {
        bgColor = schema::UI().resolveColor("var(--sidebar-hover)", IM_COL32(255, 255, 255, 25));
    } else if (hovered && !spec.disabled) {
        bgColor = schema::UI().resolveColor("var(--active-overlay)", IM_COL32(255, 255, 255, 10));
    }
    
    if (bgColor) {
        drawList->AddRectFilled(itemBB.Min, itemBB.Max, bgColor, size::ButtonCornerRadius);
    }
    
    // Selected indicator (left edge)
    if (spec.selected) {
        drawList->AddRectFilled(
            ImVec2(itemBB.Min.x, itemBB.Min.y + 8.0f),
            ImVec2(itemBB.Min.x + 4.0f, itemBB.Max.y - 8.0f),
            Primary(), 2.0f
        );
    }
    
    // Content
    float contentX = pos.x + horizontalPadding;
    float centerY = pos.y + itemHeight * 0.5f;
    
    ImU32 iconColor = spec.disabled ? OnSurfaceDisabled() :
                      spec.selected ? Primary() : OnSurfaceMedium();
    ImU32 labelColor = spec.disabled ? OnSurfaceDisabled() :
                       spec.selected ? Primary() : OnSurface();
    
    // Icon
    if (spec.icon) {
        drawList->AddText(
            ImVec2(contentX, centerY - iconSize * 0.5f),
            iconColor, spec.icon
        );
        contentX += iconSize + spacing::dp(2);  // 16dp gap after icon
    }
    
    // Label
    Typography::instance().pushFont(TypeStyle::Body1);
    float labelY = centerY - ImGui::GetFontSize() * 0.5f;
    drawList->AddText(ImVec2(contentX, labelY), labelColor, spec.label);
    Typography::instance().popFont();
    
    // Badge
    if (spec.badgeCount > 0) {
        char badgeText[8];
        if (spec.badgeCount > 999) {
            snprintf(badgeText, sizeof(badgeText), "999+");
        } else {
            snprintf(badgeText, sizeof(badgeText), "%d", spec.badgeCount);
        }
        
        ImVec2 badgeSize = ImGui::CalcTextSize(badgeText);
        float badgeWidth = ImMax(24.0f, badgeSize.x + 12.0f);
        float badgeHeight = 20.0f;
        float badgeX = itemBB.Max.x - horizontalPadding - badgeWidth;
        float badgeY = centerY - badgeHeight * 0.5f;
        
        drawList->AddRectFilled(
            ImVec2(badgeX, badgeY),
            ImVec2(badgeX + badgeWidth, badgeY + badgeHeight),
            Primary(), badgeHeight * 0.5f
        );
        
        Typography::instance().pushFont(TypeStyle::Caption);
        ImVec2 textPos(badgeX + (badgeWidth - badgeSize.x) * 0.5f, badgeY + (badgeHeight - badgeSize.y) * 0.5f);
        drawList->AddText(textPos, OnPrimary(), badgeText);
        Typography::instance().popFont();
    }
    
    ImGui::PopID();
    
    return pressed;
}

inline bool NavItem(const char* icon, const char* label, bool selected) {
    NavItemSpec spec;
    spec.icon = icon;
    spec.label = label;
    spec.selected = selected;
    return NavItem(spec);
}

inline void NavDivider() {
    ImGuiWindow* window = ImGui::GetCurrentWindow();
    if (window->SkipItems)
        return;
    
    ImVec2 pos = window->DC.CursorPos;
    ImDrawList* drawList = window->DrawList;
    
    ImGui::Dummy(ImVec2(0, spacing::dp(1)));  // 8dp spacing above
    
    drawList->AddLine(
        ImVec2(pos.x + spacing::dp(2), pos.y + spacing::dp(1)),
        ImVec2(pos.x + g_navDrawerState.width - spacing::dp(2), pos.y + spacing::dp(1)),
        OnSurfaceDisabled()
    );
    
    ImGui::Dummy(ImVec2(0, spacing::dp(1)));  // 8dp spacing below
}

inline void NavSubheader(const char* text) {
    ImGui::Dummy(ImVec2(0, spacing::dp(1)));  // 8dp above
    
    ImVec2 pos = ImGui::GetCursorScreenPos();
    ImGui::SetCursorScreenPos(ImVec2(pos.x + spacing::dp(2), pos.y));
    
    Typography::instance().textColored(TypeStyle::Caption, OnSurfaceMedium(), text);
    
    ImGui::Dummy(ImVec2(0, spacing::dp(1)));  // 8dp below
}

} // namespace material
} // namespace ui
} // namespace dragonx
