// 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 "../tooltip_style.h"
#include "imgui.h"
#include "imgui_internal.h"

namespace dragonx {
namespace ui {
namespace material {

// ============================================================================
// Material Design Button Components
// ============================================================================
// Based on https://m2.material.io/components/buttons
//
// Three button variants:
// - Text Button: Low emphasis, no container
// - Outlined Button: Medium emphasis, border only
// - Contained Button: High emphasis, filled background

enum class ButtonStyle {
    Text,      // Low emphasis - text only
    Outlined,  // Medium emphasis - border
    Contained  // High emphasis - filled (default)
};

/**
 * @brief Button configuration
 */
struct ButtonSpec {
    ButtonStyle style = ButtonStyle::Contained;
    bool enabled = true;
    bool fullWidth = false;
    const char* icon = nullptr;  // Leading icon (text glyph)
    ImU32 color = 0;             // 0 = use primary color
};

/**
 * @brief Render a Material Design button
 * 
 * @param label Button text (will be uppercased per Material spec)
 * @param spec Button configuration
 * @return true if clicked
 */
bool Button(const char* label, const ButtonSpec& spec = ButtonSpec());

/**
 * @brief Render a text-only button (low emphasis)
 */
inline bool TextButton(const char* label, bool enabled = true) {
    ButtonSpec spec;
    spec.style = ButtonStyle::Text;
    spec.enabled = enabled;
    return Button(label, spec);
}

/**
 * @brief Render an outlined button (medium emphasis)
 */
inline bool OutlinedButton(const char* label, bool enabled = true) {
    ButtonSpec spec;
    spec.style = ButtonStyle::Outlined;
    spec.enabled = enabled;
    return Button(label, spec);
}

/**
 * @brief Render a contained/filled button (high emphasis)
 */
inline bool ContainedButton(const char* label, bool enabled = true) {
    ButtonSpec spec;
    spec.style = ButtonStyle::Contained;
    spec.enabled = enabled;
    return Button(label, spec);
}

/**
 * @brief Render an icon button (circular touch target)
 * 
 * @param icon Icon glyph/character
 * @param tooltip Hover tooltip text
 * @param enabled Whether button is enabled
 * @return true if clicked
 */
bool IconButton(const char* icon, const char* tooltip = nullptr, bool enabled = true);

/**
 * @brief Render a Floating Action Button (FAB)
 * 
 * @param icon Icon glyph
 * @param label Optional label for extended FAB
 * @param mini Use mini size (40dp instead of 56dp)
 * @return true if clicked
 */
bool FAB(const char* icon, const char* label = nullptr, bool mini = false);

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

inline bool Button(const char* label, const ButtonSpec& spec) {
    ImGuiWindow* window = ImGui::GetCurrentWindow();
    if (window->SkipItems)
        return false;
    
    ImGuiContext& g = *GImGui;
    const ImGuiStyle& style = g.Style;
    const ImGuiID id = window->GetID(label);
    
    // Convert label to uppercase for Material Design
    char upperLabel[256];
    {
        const char* src = label;
        char* dst = upperLabel;
        char* end = upperLabel + sizeof(upperLabel) - 1;
        while (*src && dst < end) {
            *dst++ = (char)toupper((unsigned char)*src++);
        }
        *dst = '\0';
    }
    
    // Get button font
    ImFont* buttonFont = Typography::instance().button();
    ImGui::PushFont(buttonFont);
    
    // Calculate button size
    ImVec2 labelSize = ImGui::CalcTextSize(upperLabel);
    float iconWidth = spec.icon ? (size::IconSize + size::ButtonIconGap) : 0.0f;
    
    ImVec2 buttonSize;
    buttonSize.x = spec.fullWidth ? ImGui::GetContentRegionAvail().x 
                                  : ImMax(labelSize.x + iconWidth + size::ButtonPaddingH * 2, size::ButtonMinWidth);
    buttonSize.y = size::ButtonHeight;
    
    // Get position
    ImVec2 pos = window->DC.CursorPos;
    ImRect bb(pos, ImVec2(pos.x + buttonSize.x, pos.y + buttonSize.y));
    
    ImGui::ItemSize(buttonSize, style.FramePadding.y);
    if (!ImGui::ItemAdd(bb, id)) {
        ImGui::PopFont();
        return false;
    }
    
    // Handle interaction
    bool hovered, held;
    bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held, 0);
    
    if (!spec.enabled) {
        hovered = held = false;
    }
    
    if (hovered) ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
    
    // Get colors
    ImU32 primaryColor = spec.color ? spec.color : Primary();
    ImU32 textColor;
    ImU32 bgColor;
    ImU32 borderColor = 0;
    
    switch (spec.style) {
        case ButtonStyle::Text:
            bgColor = 0;  // No background
            textColor = spec.enabled ? primaryColor : OnSurfaceDisabled();
            if (hovered) bgColor = BlendOverlay(Surface(), StateHover(), 1.0f);
            if (held) bgColor = BlendOverlay(Surface(), StatePressed(), 1.0f);
            break;
            
        case ButtonStyle::Outlined:
            bgColor = 0;  // No background
            textColor = spec.enabled ? primaryColor : OnSurfaceDisabled();
            borderColor = spec.enabled ? primaryColor : OnSurfaceDisabled();
            if (hovered) bgColor = BlendOverlay(Surface(), StateHover(), 1.0f);
            if (held) bgColor = BlendOverlay(Surface(), StatePressed(), 1.0f);
            break;
            
        case ButtonStyle::Contained:
        default:
            if (spec.enabled) {
                bgColor = primaryColor;
                textColor = OnPrimary();
                if (hovered) bgColor = BlendOverlay(primaryColor, StateHover(), 1.0f);
                if (held) bgColor = BlendOverlay(primaryColor, StatePressed(), 1.0f);
            } else {
                bgColor = WithAlphaF(OnSurface(), 0.12f);
                textColor = OnSurfaceDisabled();
            }
            break;
    }
    
    // Render
    ImDrawList* drawList = window->DrawList;
    
    // Background
    if (bgColor) {
        drawList->AddRectFilled(bb.Min, bb.Max, bgColor, size::ButtonCornerRadius);
    }
    
    // Border (for outlined)
    if (borderColor) {
        drawList->AddRect(bb.Min, bb.Max, borderColor, size::ButtonCornerRadius, 0, 1.0f);
    }
    
    // Icon
    float contentX = bb.Min.x + size::ButtonPaddingH;
    float contentY = bb.Min.y + (buttonSize.y - labelSize.y) * 0.5f;
    
    if (spec.icon) {
        ImFont* iconFont = Type().iconMed();
        ImVec2 iconSize = iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0, spec.icon);
        ImVec2 iconPos(contentX, bb.Min.y + (buttonSize.y - iconSize.y) * 0.5f);
        drawList->AddText(iconFont, iconFont->LegacySize, iconPos, textColor, spec.icon);
        contentX += iconSize.x + size::ButtonIconGap;
    }
    
    // Label
    drawList->AddText(ImVec2(contentX, contentY), textColor, upperLabel);
    
    ImGui::PopFont();
    
    return pressed && spec.enabled;
}

inline bool IconButton(const char* icon, const char* tooltip, bool enabled) {
    ImGuiWindow* window = ImGui::GetCurrentWindow();
    if (window->SkipItems)
        return false;
    
    ImGuiContext& g = *GImGui;
    const ImGuiID id = window->GetID(icon);
    
    ImVec2 pos = window->DC.CursorPos;
    ImVec2 size(size::IconButtonSize, size::IconButtonSize);
    ImRect bb(pos, ImVec2(pos.x + size.x, pos.y + size.y));
    
    ImGui::ItemSize(size);
    if (!ImGui::ItemAdd(bb, id))
        return false;
    
    bool hovered, held;
    bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held, 0);
    
    if (!enabled) {
        hovered = held = false;
    }
    
    if (hovered) ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
    
    // Render ripple/hover circle
    ImDrawList* drawList = window->DrawList;
    ImVec2 center = bb.GetCenter();
    float radius = size::IconButtonSize * 0.5f;
    
    if (hovered || held) {
        ImU32 overlayColor = held ? StatePressed() : StateHover();
        drawList->AddCircleFilled(center, radius, overlayColor);
    }
    
    // Render icon (use icon font)
    ImFont* iconFont = Type().iconMed();
    ImU32 iconColor = enabled ? OnSurface() : OnSurfaceDisabled();
    ImVec2 iconSize = iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0, icon);
    ImVec2 iconPos(center.x - iconSize.x * 0.5f, center.y - iconSize.y * 0.5f);
    drawList->AddText(iconFont, iconFont->LegacySize, iconPos, iconColor, icon);
    
    // Tooltip
    if (tooltip && hovered) {
        material::Tooltip("%s", tooltip);
    }
    
    return pressed && enabled;
}

inline bool FAB(const char* icon, const char* label, bool mini) {
    ImGuiWindow* window = ImGui::GetCurrentWindow();
    if (window->SkipItems)
        return false;
    
    ImGuiContext& g = *GImGui;
    const ImGuiID id = window->GetID(icon);
    
    bool extended = (label != nullptr);
    float fabSize = mini ? size::FabMiniSize : size::FabSize;
    
    ImVec2 buttonSize;
    if (extended) {
        ImVec2 labelSize = ImGui::CalcTextSize(label);
        buttonSize.x = size::FabExtendedPadding * 2 + size::IconSize + spacing::Sm + labelSize.x;
        buttonSize.y = size::FabExtendedHeight;
    } else {
        buttonSize.x = fabSize;
        buttonSize.y = fabSize;
    }
    
    ImVec2 pos = window->DC.CursorPos;
    ImRect bb(pos, ImVec2(pos.x + buttonSize.x, pos.y + buttonSize.y));
    
    ImGui::ItemSize(buttonSize);
    if (!ImGui::ItemAdd(bb, id))
        return false;
    
    bool hovered, held;
    bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held, 0);
    
    if (hovered) ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
    
    // Colors
    ImU32 bgColor = Secondary();
    ImU32 textColor = OnSecondary();
    
    if (hovered) bgColor = BlendOverlay(bgColor, StateHover(), 1.0f);
    if (held) bgColor = BlendOverlay(bgColor, StatePressed(), 1.0f);
    
    // Render
    ImDrawList* drawList = window->DrawList;
    float radius = extended ? size::FabCornerRadius : (fabSize * 0.5f);
    drawList->AddRectFilled(bb.Min, bb.Max, bgColor, radius);
    
    // Icon
    ImVec2 center = bb.GetCenter();
    ImFont* iconFont = Type().iconMed();
    if (extended) {
        ImVec2 iconSize = iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0, icon);
        float iconX = bb.Min.x + size::FabExtendedPadding;
        float iconY = center.y - iconSize.y * 0.5f;
        drawList->AddText(iconFont, iconFont->LegacySize, ImVec2(iconX, iconY), textColor, icon);
        
        // Label
        Typography::instance().pushFont(TypeStyle::Button);
        float labelX = iconX + iconSize.x + spacing::Sm;
        float labelY = center.y - ImGui::GetFontSize() * 0.5f;
        drawList->AddText(ImVec2(labelX, labelY), textColor, label);
        Typography::instance().popFont();
    } else {
        ImVec2 iconSize = iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0, icon);
        ImVec2 iconPos(center.x - iconSize.x * 0.5f, center.y - iconSize.y * 0.5f);
        drawList->AddText(iconFont, iconFont->LegacySize, iconPos, textColor, icon);
    }
    
    return pressed;
}

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