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

namespace dragonx {
namespace ui {
namespace material {

// ============================================================================
// Material Design Snackbar Component
// ============================================================================
// Based on https://m2.material.io/components/snackbars
//
// Snackbars provide brief messages about app processes at the bottom of the
// screen. They can include a single action.

/**
 * @brief Snackbar configuration
 */
struct SnackbarSpec {
    const char* message = nullptr;         // Message text
    const char* actionText = nullptr;      // Optional action button text
    float duration = 4.0f;                 // Duration in seconds (0 = indefinite)
    bool multiLine = false;                // Allow multi-line message
};

/**
 * @brief Snackbar manager for showing notifications
 */
class Snackbar {
public:
    static Snackbar& instance();
    
    /**
     * @brief Show a snackbar message
     * 
     * @param message Message text
     * @param actionText Optional action text
     * @param duration Display duration (0 = until dismissed)
     */
    void show(const char* message, const char* actionText = nullptr, float duration = 4.0f);
    
    /**
     * @brief Show a snackbar with full configuration
     */
    void show(const SnackbarSpec& spec);
    
    /**
     * @brief Dismiss current snackbar
     */
    void dismiss();
    
    /**
     * @brief Render snackbar (call each frame)
     * 
     * @return true if action was clicked
     */
    bool render();
    
    /**
     * @brief Check if snackbar is visible
     */
    bool isVisible() const { return m_visible; }
    
private:
    Snackbar() = default;
    
    bool m_visible = false;
    SnackbarSpec m_currentSpec;
    float m_showTime = 0;
    float m_animProgress = 0;  // 0 = hidden, 1 = fully shown
};

// ============================================================================
// Convenience Functions
// ============================================================================

/**
 * @brief Show a snackbar message
 */
inline void ShowSnackbar(const char* message, const char* action = nullptr, float duration = 4.0f) {
    Snackbar::instance().show(message, action, duration);
}

/**
 * @brief Dismiss current snackbar
 */
inline void DismissSnackbar() {
    Snackbar::instance().dismiss();
}

/**
 * @brief Render snackbar system (call once per frame in main render loop)
 * 
 * @return true if action was clicked
 */
inline bool RenderSnackbar() {
    return Snackbar::instance().render();
}

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

inline Snackbar& Snackbar::instance() {
    static Snackbar s_instance;
    return s_instance;
}

inline void Snackbar::show(const char* message, const char* actionText, float duration) {
    SnackbarSpec spec;
    spec.message = message;
    spec.actionText = actionText;
    spec.duration = duration;
    show(spec);
}

inline void Snackbar::show(const SnackbarSpec& spec) {
    m_currentSpec = spec;
    m_visible = true;
    m_showTime = (float)ImGui::GetTime();
    m_animProgress = 0;
}

inline void Snackbar::dismiss() {
    m_visible = false;
}

inline bool Snackbar::render() {
    if (!m_visible && m_animProgress <= 0)
        return false;
    
    bool actionClicked = false;
    float currentTime = (float)ImGui::GetTime();
    
    // Check auto-dismiss
    if (m_visible && m_currentSpec.duration > 0) {
        if (currentTime - m_showTime > m_currentSpec.duration) {
            m_visible = false;
        }
    }
    
    // Animate in/out
    float animTarget = m_visible ? 1.0f : 0.0f;
    float animSpeed = 8.0f;  // Animation speed
    if (m_animProgress < animTarget) {
        m_animProgress = ImMin(m_animProgress + ImGui::GetIO().DeltaTime * animSpeed, animTarget);
    } else if (m_animProgress > animTarget) {
        m_animProgress = ImMax(m_animProgress - ImGui::GetIO().DeltaTime * animSpeed, animTarget);
    }
    
    if (m_animProgress <= 0)
        return false;
    
    // Snackbar dimensions
    const float snackbarHeight = m_currentSpec.multiLine ? 68.0f : 48.0f;
    const float snackbarMinWidth = 344.0f;
    const float snackbarMaxWidth = 672.0f;
    const float margin = spacing::dp(3);  // 24dp from edges
    
    ImGuiIO& io = ImGui::GetIO();
    
    // Calculate width based on content
    float messageWidth = ImGui::CalcTextSize(m_currentSpec.message).x;
    float actionWidth = m_currentSpec.actionText ? 
        ImGui::CalcTextSize(m_currentSpec.actionText).x + spacing::dp(2) : 0;
    float contentWidth = messageWidth + actionWidth + spacing::dp(4);  // 32dp padding
    float snackbarWidth = ImClamp(contentWidth, snackbarMinWidth, snackbarMaxWidth);
    
    // Position at bottom center
    float bottomY = io.DisplaySize.y - margin - snackbarHeight;
    float slideOffset = (1.0f - m_animProgress) * (snackbarHeight + margin);
    
    ImVec2 snackbarPos(
        (io.DisplaySize.x - snackbarWidth) * 0.5f,
        bottomY + slideOffset
    );
    
    // Draw snackbar
    ImDrawList* drawList = ImGui::GetForegroundDrawList();
    
    // Background (elevation dp6 equivalent)
    ImU32 snackBg = schema::UI().resolveColor("var(--snackbar-bg)", IM_COL32(50, 50, 50, 255));
    ImU32 bgColor = ScaleAlpha(snackBg, m_animProgress);
    ImVec2 snackbarMin = snackbarPos;
    ImVec2 snackbarMax(snackbarPos.x + snackbarWidth, snackbarPos.y + snackbarHeight);
    
    drawList->AddRectFilled(snackbarMin, snackbarMax, bgColor, 4.0f);
    
    // Message text
    float textY = snackbarPos.y + (snackbarHeight - ImGui::GetFontSize()) * 0.5f;
    float textX = snackbarPos.x + spacing::dp(2);  // 16dp left padding
    
    ImU32 snackText = schema::UI().resolveColor("var(--snackbar-text)", IM_COL32(255, 255, 255, 222));
    ImU32 textColor = ScaleAlpha(snackText, m_animProgress);
    drawList->AddText(ImVec2(textX, textY), textColor, m_currentSpec.message);
    
    // Action button
    if (m_currentSpec.actionText) {
        float actionX = snackbarMax.x - spacing::dp(2) - actionWidth;
        
        // Hit test for action
        ImVec2 actionMin(actionX, snackbarPos.y);
        ImVec2 actionMax(snackbarMax.x, snackbarMax.y);
        
        ImVec2 mousePos = io.MousePos;
        bool hovered = (mousePos.x >= actionMin.x && mousePos.x < actionMax.x &&
                       mousePos.y >= actionMin.y && mousePos.y < actionMax.y);
        
        // Action text color
        ImU32 actionColor;
        if (hovered) {
            actionColor = ScaleAlpha(schema::UI().resolveColor("var(--snackbar-action-hover)", IM_COL32(255, 213, 79, 255)), m_animProgress);
        } else {
            actionColor = ScaleAlpha(schema::UI().resolveColor("var(--snackbar-action)", IM_COL32(255, 193, 7, 255)), m_animProgress);
        }
        
        drawList->AddText(ImVec2(actionX, textY), actionColor, m_currentSpec.actionText);
        
        // Check click
        if (hovered && io.MouseClicked[0]) {
            actionClicked = true;
            dismiss();
        }
    }
    
    return actionClicked;
}

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