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

namespace dragonx {
namespace ui {
namespace material {

// ============================================================================
// Material Design List Component
// ============================================================================
// Based on https://m2.material.io/components/lists
//
// Lists present content in a way that makes it easy to identify a specific
// item in a collection and act on it.

/**
 * @brief List item configuration
 */
struct ListItemSpec {
    const char* leadingIcon = nullptr;     // Optional leading icon (text representation)
    const char* leadingAvatar = nullptr;   // Optional avatar text (for initials)
    ImU32 leadingAvatarColor = 0;          // Avatar background color (0 = primary)
    bool leadingCheckbox = false;          // Show checkbox instead of icon
    bool checkboxChecked = false;          // Checkbox state
    const char* primaryText = nullptr;     // Main text (required)
    const char* secondaryText = nullptr;   // Secondary text (optional)
    const char* trailingIcon = nullptr;    // Optional trailing icon
    const char* trailingText = nullptr;    // Optional trailing metadata text
    bool selected = false;                 // Selected state (highlight)
    bool disabled = false;                 // Disabled state
    bool dividerBelow = false;             // Draw divider below item
};

/**
 * @brief Begin a list container
 * 
 * @param id Unique identifier
 * @param withPadding Add top/bottom padding
 */
void BeginList(const char* id, bool withPadding = true);

/**
 * @brief End a list container
 */
void EndList();

/**
 * @brief Render a list item
 * 
 * @param spec Item configuration
 * @return true if clicked
 */
bool ListItem(const ListItemSpec& spec);

/**
 * @brief Simple single-line list item
 */
bool ListItem(const char* text);

/**
 * @brief Two-line list item with primary and secondary text
 */
bool ListItem(const char* primary, const char* secondary);

/**
 * @brief List divider (full width or inset)
 * 
 * @param inset If true, indented to align with text
 */
void ListDivider(bool inset = false);

/**
 * @brief List subheader text
 */
void ListSubheader(const char* text);

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

inline void BeginList(const char* id, bool withPadding) {
    ImGui::PushID(id);
    if (withPadding) {
        ImGui::Dummy(ImVec2(0, spacing::dp(1)));  // 8dp top padding
    }
}

inline void EndList() {
    ImGui::PopID();
}

inline bool ListItem(const ListItemSpec& spec) {
    ImGuiWindow* window = ImGui::GetCurrentWindow();
    if (window->SkipItems)
        return false;
    
    // Calculate item height based on content
    bool hasSecondary = (spec.secondaryText != nullptr);
    bool hasLeadingElement = (spec.leadingIcon || spec.leadingAvatar || spec.leadingCheckbox);
    
    float itemHeight;
    if (hasSecondary) {
        itemHeight = size::ListItemTwoLineHeight;  // 72dp for two-line
    } else if (hasLeadingElement) {
        itemHeight = size::ListItemHeight;  // 56dp with leading element
    } else {
        itemHeight = 48.0f;  // 48dp simple one-line
    }
    
    // Item dimensions
    ImVec2 pos = window->DC.CursorPos;
    float itemWidth = ImGui::GetContentRegionAvail().x;
    ImRect bb(pos, ImVec2(pos.x + itemWidth, pos.y + itemHeight));
    
    // Interaction
    ImGuiID itemId = window->GetID(spec.primaryText);
    ImGui::ItemSize(bb);
    if (!ImGui::ItemAdd(bb, itemId))
        return false;
    
    bool hovered, held;
    bool pressed = ImGui::ButtonBehavior(bb, itemId, &hovered, &held) && !spec.disabled;
    
    // Draw background
    ImDrawList* drawList = window->DrawList;
    ImU32 bgColor = 0;
    
    if (spec.selected) {
        bgColor = PrimaryContainer();
    } else if (held && !spec.disabled) {
        bgColor = schema::UI().resolveColor("var(--hover-overlay)", 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(bb.Min, bb.Max, bgColor);
    }
    
    // Layout positions
    float leftPadding = spacing::dp(2);  // 16dp left padding
    float currentX = bb.Min.x + leftPadding;
    float centerY = bb.Min.y + itemHeight * 0.5f;
    
    // Draw leading element
    if (spec.leadingAvatar) {
        // Avatar circle with text
        float avatarRadius = 20.0f;  // 40dp diameter
        ImVec2 avatarCenter(currentX + avatarRadius, centerY);
        
        ImU32 avatarBg = spec.leadingAvatarColor ? spec.leadingAvatarColor : Primary();
        drawList->AddCircleFilled(avatarCenter, avatarRadius, avatarBg);
        
        // Avatar text (centered)
        ImVec2 textSize = ImGui::CalcTextSize(spec.leadingAvatar);
        ImVec2 textPos(avatarCenter.x - textSize.x * 0.5f, avatarCenter.y - textSize.y * 0.5f);
        drawList->AddText(textPos, OnPrimary(), spec.leadingAvatar);
        
        currentX += 40.0f + spacing::dp(2);  // 40dp avatar + 16dp gap
    } else if (spec.leadingIcon) {
        // Icon
        ImVec2 iconSize = ImGui::CalcTextSize(spec.leadingIcon);
        float iconY = centerY - iconSize.y * 0.5f;
        ImU32 iconColor = spec.disabled ? OnSurfaceDisabled() : OnSurfaceMedium();
        drawList->AddText(ImVec2(currentX, iconY), iconColor, spec.leadingIcon);
        currentX += 24.0f + spacing::dp(2);  // 24dp icon + 16dp gap
    } else if (spec.leadingCheckbox) {
        // Checkbox (simplified visual)
        float checkboxSize = 18.0f;
        ImVec2 checkMin(currentX, centerY - checkboxSize * 0.5f);
        ImVec2 checkMax(currentX + checkboxSize, centerY + checkboxSize * 0.5f);
        
        if (spec.checkboxChecked) {
            drawList->AddRectFilled(checkMin, checkMax, Primary(), 2.0f);
            // Checkmark
            ImFont* iconFont = Typography::instance().iconSmall();
            ImVec2 chkSz = iconFont->CalcTextSizeA(iconFont->LegacySize, 1000.0f, 0.0f, ICON_MD_CHECK);
            drawList->AddText(iconFont, iconFont->LegacySize,
                ImVec2(checkMin.x + (checkboxSize - chkSz.x) * 0.5f, checkMin.y + (checkboxSize - chkSz.y) * 0.5f),
                OnPrimary(), ICON_MD_CHECK);
        } else {
            drawList->AddRect(checkMin, checkMax, OnSurfaceMedium(), 2.0f, 0, 2.0f);
        }
        
        currentX += checkboxSize + spacing::dp(2);
    }
    
    // Calculate text area
    float rightPadding = spacing::dp(2);  // 16dp right padding
    float trailingSpace = 0;
    if (spec.trailingIcon) trailingSpace += 24.0f + spacing::dp(1);
    if (spec.trailingText) trailingSpace += ImGui::CalcTextSize(spec.trailingText).x + spacing::dp(1);
    
    float textMaxX = bb.Max.x - rightPadding - trailingSpace;
    
    // Draw text
    ImU32 primaryColor = spec.disabled ? OnSurfaceDisabled() : OnSurface();
    ImU32 secondaryColor = spec.disabled ? OnSurfaceDisabled() : OnSurfaceMedium();
    
    if (hasSecondary) {
        // Two-line layout
        float primaryY = bb.Min.y + 16.0f;
        float secondaryY = primaryY + 20.0f;
        
        Typography::instance().pushFont(TypeStyle::Body1);
        drawList->AddText(ImVec2(currentX, primaryY), primaryColor, spec.primaryText);
        Typography::instance().popFont();
        
        Typography::instance().pushFont(TypeStyle::Body2);
        drawList->AddText(ImVec2(currentX, secondaryY), secondaryColor, spec.secondaryText);
        Typography::instance().popFont();
    } else {
        // Single-line layout
        Typography::instance().pushFont(TypeStyle::Body1);
        float textY = centerY - Typography::instance().getFont(TypeStyle::Body1)->FontSize * 0.5f;
        drawList->AddText(ImVec2(currentX, textY), primaryColor, spec.primaryText);
        Typography::instance().popFont();
    }
    
    // Draw trailing elements
    float trailingX = bb.Max.x - rightPadding;
    
    if (spec.trailingText) {
        ImVec2 textSize = ImGui::CalcTextSize(spec.trailingText);
        trailingX -= textSize.x;
        float textY = centerY - textSize.y * 0.5f;
        drawList->AddText(ImVec2(trailingX, textY), secondaryColor, spec.trailingText);
        trailingX -= spacing::dp(1);
    }
    
    if (spec.trailingIcon) {
        ImVec2 iconSize = ImGui::CalcTextSize(spec.trailingIcon);
        trailingX -= 24.0f;
        float iconY = centerY - iconSize.y * 0.5f;
        drawList->AddText(ImVec2(trailingX, iconY), OnSurfaceMedium(), spec.trailingIcon);
    }
    
    // Draw divider
    if (spec.dividerBelow) {
        float dividerY = bb.Max.y - 0.5f;
        drawList->AddLine(
            ImVec2(bb.Min.x + leftPadding, dividerY),
            ImVec2(bb.Max.x, dividerY),
            OnSurfaceDisabled()
        );
    }
    
    return pressed;
}

inline bool ListItem(const char* text) {
    ListItemSpec spec;
    spec.primaryText = text;
    return ListItem(spec);
}

inline bool ListItem(const char* primary, const char* secondary) {
    ListItemSpec spec;
    spec.primaryText = primary;
    spec.secondaryText = secondary;
    return ListItem(spec);
}

inline void ListDivider(bool inset) {
    ImGuiWindow* window = ImGui::GetCurrentWindow();
    if (window->SkipItems)
        return;
    
    float width = ImGui::GetContentRegionAvail().x;
    float leftOffset = inset ? 72.0f : 0;  // Align with text after avatar/icon
    
    ImVec2 pos = window->DC.CursorPos;
    ImDrawList* drawList = window->DrawList;
    
    drawList->AddLine(
        ImVec2(pos.x + leftOffset, pos.y),
        ImVec2(pos.x + width, pos.y),
        OnSurfaceDisabled()
    );
    
    ImGui::Dummy(ImVec2(width, 1.0f));
}

inline void ListSubheader(const char* text) {
    ImGui::Dummy(ImVec2(0, spacing::dp(1)));  // 8dp top padding
    
    ImGui::SetCursorPosX(ImGui::GetCursorPosX() + spacing::dp(2));  // 16dp left padding
    Typography::instance().textColored(TypeStyle::Caption, Primary(), text);
    
    ImGui::Dummy(ImVec2(0, spacing::dp(1)));  // 8dp bottom padding
}

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