// 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 Tabs Component
// ============================================================================
// Based on https://m2.material.io/components/tabs
//
// Tabs organize content across different screens, data sets, and other
// interactions.

/**
 * @brief Tab bar configuration
 */
struct TabBarSpec {
    bool scrollable = false;      // Enable horizontal scrolling
    bool fullWidth = true;        // Tabs fill available width
    bool showIndicator = true;    // Show selection indicator
    bool centered = false;        // Center tabs (when not full width)
};

/**
 * @brief Individual tab configuration
 */
struct TabSpec {
    const char* label = nullptr;
    const char* icon = nullptr;   // Optional icon (text representation)
    bool disabled = false;
    int badgeCount = 0;           // Badge count (0 = no badge)
};

/**
 * @brief Begin a tab bar
 * 
 * @param id Unique identifier
 * @param selectedIndex Pointer to selected tab index
 * @param spec Tab bar configuration
 * @return true if tab bar is visible
 */
bool BeginTabBar(const char* id, int* selectedIndex, const TabBarSpec& spec = TabBarSpec());

/**
 * @brief End a tab bar
 */
void EndTabBar();

/**
 * @brief Add a tab to current tab bar
 * 
 * @param spec Tab configuration
 * @return true if this tab is selected
 */
bool Tab(const TabSpec& spec);

/**
 * @brief Simple tab with just label
 */
bool Tab(const char* label);

/**
 * @brief Simple tab bar - returns selected index
 * 
 * @param id Unique identifier
 * @param labels Array of tab labels
 * @param count Number of tabs
 * @param selectedIndex Current selected index (will be updated)
 * @return true if selection changed
 */
bool TabBar(const char* id, const char** labels, int count, int* selectedIndex);

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

// Internal state for tab rendering
struct TabBarState {
    int* selectedIndex;
    int currentTabIndex;
    TabBarSpec spec;
    float tabBarWidth;
    float tabWidth;
    float indicatorX;
    float indicatorWidth;
    ImVec2 barPos;
};

static TabBarState g_tabBarState;

inline bool BeginTabBar(const char* id, int* selectedIndex, const TabBarSpec& spec) {
    ImGuiWindow* window = ImGui::GetCurrentWindow();
    if (window->SkipItems)
        return false;
    
    ImGui::PushID(id);
    
    g_tabBarState.selectedIndex = selectedIndex;
    g_tabBarState.currentTabIndex = 0;
    g_tabBarState.spec = spec;
    g_tabBarState.tabBarWidth = ImGui::GetContentRegionAvail().x;
    g_tabBarState.tabWidth = 0;  // Will be calculated if fullWidth
    g_tabBarState.barPos = window->DC.CursorPos;
    g_tabBarState.indicatorX = 0;
    g_tabBarState.indicatorWidth = 0;
    
    // Reserve space for tab bar
    float barHeight = size::TabBarHeight;
    ImRect bb(g_tabBarState.barPos, 
              ImVec2(g_tabBarState.barPos.x + g_tabBarState.tabBarWidth, 
                     g_tabBarState.barPos.y + barHeight));
    
    ImGui::ItemSize(bb);
    
    // Draw tab bar background
    ImDrawList* drawList = window->DrawList;
    drawList->AddRectFilled(bb.Min, bb.Max, Surface(Elevation::Dp4));
    
    // Begin horizontal layout for tabs
    ImGui::SetCursorScreenPos(g_tabBarState.barPos);
    ImGui::BeginGroup();
    
    return true;
}

inline void EndTabBar() {
    ImGui::EndGroup();
    
    // Draw indicator line
    if (g_tabBarState.spec.showIndicator && g_tabBarState.indicatorWidth > 0) {
        ImGuiWindow* window = ImGui::GetCurrentWindow();
        ImDrawList* drawList = window->DrawList;
        
        float indicatorY = g_tabBarState.barPos.y + size::TabBarHeight - 2.0f;
        drawList->AddRectFilled(
            ImVec2(g_tabBarState.indicatorX, indicatorY),
            ImVec2(g_tabBarState.indicatorX + g_tabBarState.indicatorWidth, indicatorY + 2.0f),
            Primary()
        );
    }
    
    // Add bottom divider
    ImGuiWindow* window = ImGui::GetCurrentWindow();
    ImDrawList* drawList = window->DrawList;
    float dividerY = g_tabBarState.barPos.y + size::TabBarHeight;
    drawList->AddLine(
        ImVec2(g_tabBarState.barPos.x, dividerY),
        ImVec2(g_tabBarState.barPos.x + g_tabBarState.tabBarWidth, dividerY),
        OnSurfaceDisabled()
    );
    
    ImGui::PopID();
}

inline bool Tab(const TabSpec& spec) {
    ImGuiWindow* window = ImGui::GetCurrentWindow();
    if (window->SkipItems)
        return false;
    
    int tabIndex = g_tabBarState.currentTabIndex++;
    bool isSelected = (*g_tabBarState.selectedIndex == tabIndex);
    
    // Calculate tab dimensions
    float minTabWidth = spec.icon ? 72.0f : 90.0f;  // Material min widths
    float maxTabWidth = 360.0f;
    float labelWidth = ImGui::CalcTextSize(spec.label).x;
    float iconWidth = spec.icon ? 24.0f + spacing::dp(1) : 0;
    float contentWidth = labelWidth + iconWidth + spacing::dp(4);  // 32dp padding
    
    float tabWidth;
    if (g_tabBarState.spec.fullWidth) {
        // Divide evenly (assuming we don't know total count here - simplified)
        tabWidth = ImMax(minTabWidth, contentWidth);
    } else {
        tabWidth = ImClamp(contentWidth, minTabWidth, maxTabWidth);
    }
    
    float tabHeight = size::TabBarHeight;
    
    ImVec2 tabPos = window->DC.CursorPos;
    ImRect tabBB(tabPos, ImVec2(tabPos.x + tabWidth, tabPos.y + tabHeight));
    
    // Interaction
    ImGuiID id = window->GetID(spec.label);
    bool hovered, held;
    bool pressed = ImGui::ButtonBehavior(tabBB, id, &hovered, &held) && !spec.disabled;
    
    if (pressed && !isSelected) {
        *g_tabBarState.selectedIndex = tabIndex;
    }
    
    // Update indicator position for selected tab
    if (isSelected) {
        g_tabBarState.indicatorX = tabPos.x;
        g_tabBarState.indicatorWidth = tabWidth;
    }
    
    // Draw
    ImDrawList* drawList = window->DrawList;
    
    // Hover/press state overlay
    if (!spec.disabled) {
        if (held) {
            drawList->AddRectFilled(tabBB.Min, tabBB.Max, schema::UI().resolveColor("var(--hover-overlay)", IM_COL32(255, 255, 255, 25)));
        } else if (hovered) {
            drawList->AddRectFilled(tabBB.Min, tabBB.Max, schema::UI().resolveColor("var(--active-overlay)", IM_COL32(255, 255, 255, 10)));
        }
    }
    
    // Content color
    ImU32 contentColor;
    if (spec.disabled) {
        contentColor = OnSurfaceDisabled();
    } else if (isSelected) {
        contentColor = Primary();
    } else {
        contentColor = OnSurfaceMedium();
    }
    
    // Draw content (icon and/or label)
    float contentX = tabPos.x + (tabWidth - labelWidth - iconWidth) * 0.5f;
    float centerY = tabPos.y + tabHeight * 0.5f;
    
    if (spec.icon) {
        ImFont* iconFont = Type().iconMed();
        ImVec2 iconSize = iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0, spec.icon);
        ImVec2 iconPos(contentX, centerY - iconSize.y * 0.5f);
        drawList->AddText(iconFont, iconFont->LegacySize, iconPos, contentColor, spec.icon);
        contentX += iconSize.x + spacing::Xs;
    }
    
    // Label (uppercase)
    Typography::instance().pushFont(TypeStyle::Button);
    float labelY = centerY - ImGui::GetFontSize() * 0.5f;
    
    // Convert to uppercase
    char upperLabel[128];
    size_t i = 0;
    for (const char* p = spec.label; *p && i < sizeof(upperLabel) - 1; p++, i++) {
        upperLabel[i] = (*p >= 'a' && *p <= 'z') ? (*p - 32) : *p;
    }
    upperLabel[i] = '\0';
    
    drawList->AddText(ImVec2(contentX, labelY), contentColor, upperLabel);
    Typography::instance().popFont();
    
    // Badge
    if (spec.badgeCount > 0) {
        float badgeX = tabPos.x + tabWidth - 16.0f;
        float badgeY = tabPos.y + 8.0f;
        float badgeRadius = 8.0f;
        
        drawList->AddCircleFilled(ImVec2(badgeX, badgeY), badgeRadius, Error());
        
        char badgeText[8];
        if (spec.badgeCount > 99) {
            snprintf(badgeText, sizeof(badgeText), "99+");
        } else {
            snprintf(badgeText, sizeof(badgeText), "%d", spec.badgeCount);
        }
        
        ImVec2 badgeTextSize = ImGui::CalcTextSize(badgeText);
        ImVec2 badgeTextPos(badgeX - badgeTextSize.x * 0.5f, badgeY - badgeTextSize.y * 0.5f);
        
        Typography::instance().pushFont(TypeStyle::Caption);
        drawList->AddText(badgeTextPos, OnError(), badgeText);
        Typography::instance().popFont();
    }
    
    // Advance cursor
    ImGui::SameLine(0, 0);
    ImGui::SetCursorScreenPos(ImVec2(tabPos.x + tabWidth, tabPos.y));
    
    return isSelected;
}

inline bool Tab(const char* label) {
    TabSpec spec;
    spec.label = label;
    return Tab(spec);
}

inline bool TabBar(const char* id, const char** labels, int count, int* selectedIndex) {
    int oldIndex = *selectedIndex;
    
    TabBarSpec spec;
    spec.fullWidth = true;
    
    if (BeginTabBar(id, selectedIndex, spec)) {
        // Calculate tab width for full-width mode
        float tabWidth = ImGui::GetContentRegionAvail().x / count;
        
        for (int i = 0; i < count; i++) {
            TabSpec tabSpec;
            tabSpec.label = labels[i];
            Tab(tabSpec);
        }
        
        EndTabBar();
    }
    
    return (*selectedIndex != oldIndex);
}

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