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

#pragma once

#include "../material/material.h"
#include "../../embedded/IconsMaterialDesign.h"
#include "../schema/ui_schema.h"
#include "home_screen.h"
#include "send_screen.h"
#include "receive_screen.h"
#include "transactions_screen.h"
#include "mining_screen.h"
#include "peers_screen.h"
#include "settings_screen.h"
#include "imgui.h"
#include <functional>
#include <string>

namespace dragonx {
namespace ui {
namespace screens {

using namespace material;

// ============================================================================
// Main Application Layout
// ============================================================================
// Combines app bar, navigation drawer, content area, and status bar

/**
 * @brief Navigation destinations
 */
enum class NavDestination {
    Home,
    Send,
    Receive,
    Transactions,
    Mining,
    Peers,
    Settings
};

/**
 * @brief Connection status for status bar
 */
struct ConnectionStatus {
    bool connected = false;
    int blockHeight = 0;
    int peers = 0;
    double networkHashrate = 0.0;
    bool syncing = false;
    float syncProgress = 0.0f;
    std::string statusMessage;
};

/**
 * @brief Main application layout with Material Design structure
 */
class MainLayout {
public:
    MainLayout() = default;
    
    void setConnectionStatus(const ConnectionStatus& status) { m_status = status; }
    
    void setOnNavigation(std::function<void(NavDestination)> callback) {
        m_onNavigation = callback;
    }
    
    void setOnSearch(std::function<void(const std::string&)> callback) {
        m_onSearch = callback;
    }
    
    void setOnSettingsClick(std::function<void()> callback) {
        m_onSettingsClick = callback;
    }
    
    void navigateTo(NavDestination dest) {
        m_currentDestination = dest;
        m_drawerOpen = false;  // Close drawer on navigation
    }
    
    NavDestination getCurrentDestination() const { return m_currentDestination; }
    
    // Screen access
    HomeScreen& homeScreen() { return m_homeScreen; }
    SendScreen& sendScreen() { return m_sendScreen; }
    ReceiveScreen& receiveScreen() { return m_receiveScreen; }
    TransactionsScreen& transactionsScreen() { return m_transactionsScreen; }
    MiningScreen& miningScreen() { return m_miningScreen; }
    PeersScreen& peersScreen() { return m_peersScreen; }
    SettingsScreen& settingsScreen() { return m_settingsScreen; }
    
    void render();
    
private:
    void renderAppBar();
    void renderNavigationDrawer();
    void renderContent();
    void renderStatusBar();
    void renderSearchOverlay();
    
    NavDestination m_currentDestination = NavDestination::Home;
    ConnectionStatus m_status;
    
    std::function<void(NavDestination)> m_onNavigation;
    std::function<void(const std::string&)> m_onSearch;
    std::function<void()> m_onSettingsClick;
    
    // Navigation drawer state
    bool m_drawerOpen = false;
    AnimatedValue<float> m_drawerAnimation{0.0f};
    
    // Search state
    bool m_searchOpen = false;
    char m_searchBuffer[256] = {0};
    
    // Screens
    HomeScreen m_homeScreen;
    SendScreen m_sendScreen;
    ReceiveScreen m_receiveScreen;
    TransactionsScreen m_transactionsScreen;
    MiningScreen m_miningScreen;
    PeersScreen m_peersScreen;
    SettingsScreen m_settingsScreen;
    
    // Layout values — read from ui.toml schema at runtime
    static float APP_BAR_HEIGHT;
    static float STATUS_BAR_HEIGHT;
    static float DRAWER_WIDTH;

    static void initLayoutConstants() {
        APP_BAR_HEIGHT  = schema::UI().drawElement("components.main-layout", "app-bar-height").size;
        STATUS_BAR_HEIGHT = schema::UI().drawElement("components.main-layout", "status-bar-height").size;
        DRAWER_WIDTH    = schema::UI().drawElement("components.main-layout", "drawer-width").size;
        if (APP_BAR_HEIGHT  <= 0) APP_BAR_HEIGHT  = 64.0f;
        if (STATUS_BAR_HEIGHT <= 0) STATUS_BAR_HEIGHT = 32.0f;
        if (DRAWER_WIDTH    <= 0) DRAWER_WIDTH    = 256.0f;
    }
};

// Static member definitions
inline float MainLayout::APP_BAR_HEIGHT = 64.0f;
inline float MainLayout::STATUS_BAR_HEIGHT = 32.0f;
inline float MainLayout::DRAWER_WIDTH = 256.0f;

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

inline void MainLayout::render() {
    static bool layoutInitialized = false;
    if (!layoutInitialized) {
        initLayoutConstants();
        layoutInitialized = true;
    }

    ImGuiIO& io = ImGui::GetIO();
    float windowWidth = io.DisplaySize.x;
    float windowHeight = io.DisplaySize.y;
    
    // Full-screen window
    ImGui::SetNextWindowPos(ImVec2(0, 0));
    ImGui::SetNextWindowSize(ImVec2(windowWidth, windowHeight));
    
    ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoTitleBar | 
                                   ImGuiWindowFlags_NoResize |
                                   ImGuiWindowFlags_NoMove |
                                   ImGuiWindowFlags_NoCollapse |
                                   ImGuiWindowFlags_NoBringToFrontOnFocus;
    
    ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
    ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
    ImGui::PushStyleColor(ImGuiCol_WindowBg, Background());
    
    if (ImGui::Begin("MainLayout", nullptr, windowFlags)) {
        // App bar
        renderAppBar();
        
        // Content area with optional drawer
        float contentY = APP_BAR_HEIGHT;
        float contentHeight = windowHeight - APP_BAR_HEIGHT - STATUS_BAR_HEIGHT;
        
        // Update drawer animation
        float targetDrawer = m_drawerOpen ? 1.0f : 0.0f;
        m_drawerAnimation.animateTo(targetDrawer, duration::Medium);
        m_drawerAnimation.update(io.DeltaTime);
        float drawerProgress = m_drawerAnimation.value();
        
        // Navigation drawer (slides in from left)
        if (drawerProgress > 0.01f) {
            renderNavigationDrawer();
        }
        
        // Content offset based on drawer
        float contentX = drawerProgress * DRAWER_WIDTH;
        
        // Content area
        ImGui::SetCursorPos(ImVec2(contentX, contentY));
        ImGui::BeginChild("Content", ImVec2(windowWidth - contentX, contentHeight), false,
                         ImGuiWindowFlags_NoScrollbar);
        {
            ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(spacing::dp(3), spacing::dp(3)));
            renderContent();
            ImGui::PopStyleVar();
        }
        ImGui::EndChild();
        
        // Status bar
        ImGui::SetCursorPos(ImVec2(0, windowHeight - STATUS_BAR_HEIGHT));
        renderStatusBar();
        
        // Search overlay
        if (m_searchOpen) {
            renderSearchOverlay();
        }
        
        // Click outside drawer to close
        if (m_drawerOpen && ImGui::IsMouseClicked(0)) {
            ImVec2 mousePos = ImGui::GetMousePos();
            if (mousePos.x > DRAWER_WIDTH) {
                m_drawerOpen = false;
            }
        }
    }
    ImGui::End();
    
    ImGui::PopStyleColor();
    ImGui::PopStyleVar(2);
}

inline void MainLayout::renderAppBar() {
    ImGuiIO& io = ImGui::GetIO();
    float windowWidth = io.DisplaySize.x;
    
    // App bar background
    ImVec2 appBarPos = ImGui::GetCursorScreenPos();
    ImGui::GetWindowDrawList()->AddRectFilled(
        appBarPos,
        ImVec2(appBarPos.x + windowWidth, appBarPos.y + APP_BAR_HEIGHT),
        ImGui::GetColorU32(Surface())
    );
    
    // Elevation shadow
    DrawShadow(ImVec2(appBarPos.x, appBarPos.y + APP_BAR_HEIGHT - 4),
               ImVec2(windowWidth, 4), 4);
    
    ImGui::SetCursorPos(ImVec2(spacing::dp(1), (APP_BAR_HEIGHT - schema::UI().drawElement("components.main-layout", "app-bar-button-size").size) / 2));
    
    // Menu button
    ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
    ImGui::PushStyleColor(ImGuiCol_ButtonHovered, colors::withAlpha(OnSurface(), 0.08f));
    ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, schema::UI().drawElement("components.main-layout", "app-bar-btn-rounding").size);
    
    float appBarBtnSz = schema::UI().drawElement("components.main-layout", "app-bar-button-size").size;
    if (ImGui::Button(ICON_MD_MENU, ImVec2(appBarBtnSz, appBarBtnSz))) {
        m_drawerOpen = !m_drawerOpen;
    }
    
    ImGui::PopStyleVar();
    ImGui::PopStyleColor(2);
    
    // Title
    ImGui::SameLine(0, spacing::dp(2));
    ImGui::SetCursorPosY((APP_BAR_HEIGHT - schema::UI().drawElement("components.main-layout", "title-font-height").size) / 2);
    Typography::instance().text(TypeStyle::H6, "DragonX Wallet");
    
    // Right actions
    float rightOffset = windowWidth - spacing::dp(1) - appBarBtnSz;
    
    // Settings button
    ImGui::SameLine(rightOffset);
    ImGui::SetCursorPosY((APP_BAR_HEIGHT - appBarBtnSz) / 2);
    
    ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
    ImGui::PushStyleColor(ImGuiCol_ButtonHovered, colors::withAlpha(OnSurface(), 0.08f));
    ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, schema::UI().drawElement("components.main-layout", "app-bar-btn-rounding").size);
    
    if (ImGui::Button(ICON_MD_SETTINGS, ImVec2(appBarBtnSz, appBarBtnSz))) {
        navigateTo(NavDestination::Settings);
    }
    
    // Search button
    ImGui::SameLine(rightOffset - 48);
    ImGui::SetCursorPosY((APP_BAR_HEIGHT - appBarBtnSz) / 2);
    
    if (ImGui::Button(ICON_MD_SEARCH, ImVec2(appBarBtnSz, appBarBtnSz))) {
        m_searchOpen = !m_searchOpen;
    }
    
    ImGui::PopStyleVar();
    ImGui::PopStyleColor(2);
}

inline void MainLayout::renderNavigationDrawer() {
    ImGuiIO& io = ImGui::GetIO();
    float windowHeight = io.DisplaySize.y;
    float drawerProgress = m_drawerAnimation.value();
    
    // Scrim (semi-transparent overlay)
    if (drawerProgress > 0.01f) {
        ImVec2 scrimStart = ImVec2(DRAWER_WIDTH, APP_BAR_HEIGHT);
        ImVec2 scrimEnd = ImVec2(io.DisplaySize.x, windowHeight - STATUS_BAR_HEIGHT);
        
        ImGui::GetWindowDrawList()->AddRectFilled(
            scrimStart, scrimEnd,
            ImGui::GetColorU32(ImVec4(0, 0, 0, 0.5f * drawerProgress))
        );
    }
    
    // Drawer background
    float drawerX = (drawerProgress - 1.0f) * DRAWER_WIDTH;
    ImVec2 drawerStart = ImVec2(0, APP_BAR_HEIGHT);
    ImVec2 drawerEnd = ImVec2(DRAWER_WIDTH, windowHeight - STATUS_BAR_HEIGHT);
    
    ImGui::SetCursorPos(ImVec2(drawerX, APP_BAR_HEIGHT));
    ImGui::BeginChild("NavDrawer", ImVec2(DRAWER_WIDTH, windowHeight - APP_BAR_HEIGHT - STATUS_BAR_HEIGHT),
                     false, ImGuiWindowFlags_NoScrollbar);
    {
        // Drawer surface
        ImVec2 pos = ImGui::GetCursorScreenPos();
        ImGui::GetWindowDrawList()->AddRectFilled(
            pos,
            ImVec2(pos.x + DRAWER_WIDTH, pos.y + windowHeight),
            ImGui::GetColorU32(Surface())
        );
        
        ImGui::Dummy(ImVec2(0, spacing::dp(2)));
        
        // Navigation items
        auto navItem = [this](const char* icon, const char* label, NavDestination dest) {
            bool selected = (m_currentDestination == dest);
            
            NavItemSpec spec;
            spec.icon = icon;
            spec.label = label;
            spec.selected = selected;
            
            if (NavItem(spec)) {
                navigateTo(dest);
                if (m_onNavigation) m_onNavigation(dest);
            }
        };
        
        navItem(ICON_MD_HOME, "Home", NavDestination::Home);
        navItem(ICON_MD_CALL_MADE, "Send", NavDestination::Send);
        navItem(ICON_MD_CALL_RECEIVED, "Receive", NavDestination::Receive);
        navItem(ICON_MD_RECEIPT, "Transactions", NavDestination::Transactions);
        
        ImGui::Dummy(ImVec2(0, spacing::dp(1)));
        
        // Divider
        ImVec2 divStart = ImGui::GetCursorScreenPos();
        ImGui::GetWindowDrawList()->AddLine(
            ImVec2(divStart.x + spacing::dp(2), divStart.y),
            ImVec2(divStart.x + DRAWER_WIDTH - spacing::dp(2), divStart.y),
            ImGui::GetColorU32(Divider())
        );
        ImGui::Dummy(ImVec2(0, spacing::dp(1)));
        
        navItem(ICON_MD_CONSTRUCTION, "Mining", NavDestination::Mining);
        navItem(ICON_MD_HUB, "Network", NavDestination::Peers);
        
        ImGui::Dummy(ImVec2(0, spacing::dp(1)));
        
        // Another divider
        divStart = ImGui::GetCursorScreenPos();
        ImGui::GetWindowDrawList()->AddLine(
            ImVec2(divStart.x + spacing::dp(2), divStart.y),
            ImVec2(divStart.x + DRAWER_WIDTH - spacing::dp(2), divStart.y),
            ImGui::GetColorU32(Divider())
        );
        ImGui::Dummy(ImVec2(0, spacing::dp(1)));
        
        navItem(ICON_MD_SETTINGS, "Settings", NavDestination::Settings);
    }
    ImGui::EndChild();
}

inline void MainLayout::renderContent() {
    // Padding
    ImGui::Dummy(ImVec2(0, spacing::dp(1)));
    
    switch (m_currentDestination) {
        case NavDestination::Home:
            m_homeScreen.render();
            break;
        case NavDestination::Send:
            m_sendScreen.render();
            break;
        case NavDestination::Receive:
            m_receiveScreen.render();
            break;
        case NavDestination::Transactions:
            m_transactionsScreen.render();
            break;
        case NavDestination::Mining:
            m_miningScreen.render();
            break;
        case NavDestination::Peers:
            m_peersScreen.render();
            break;
        case NavDestination::Settings:
            m_settingsScreen.render();
            break;
    }
}

inline void MainLayout::renderStatusBar() {
    ImGuiIO& io = ImGui::GetIO();
    float windowWidth = io.DisplaySize.x;
    
    // Status bar background
    ImVec2 statusPos = ImGui::GetCursorScreenPos();
    ImGui::GetWindowDrawList()->AddRectFilled(
        statusPos,
        ImVec2(statusPos.x + windowWidth, statusPos.y + STATUS_BAR_HEIGHT),
        ImGui::GetColorU32(SurfaceVariant())
    );
    
    // Top border
    ImGui::GetWindowDrawList()->AddLine(
        statusPos,
        ImVec2(statusPos.x + windowWidth, statusPos.y),
        ImGui::GetColorU32(Divider())
    );
    
    ImGui::SetCursorPos(ImVec2(spacing::dp(2), ImGui::GetCursorPosY() + 6));
    
    // Connection status
    if (m_status.connected) {
        Typography::instance().textColored(TypeStyle::Caption, colors::Green500, ICON_MD_FIBER_MANUAL_RECORD " Connected");
    } else {
        Typography::instance().textColored(TypeStyle::Caption, colors::Red500, ICON_MD_FIBER_MANUAL_RECORD " Disconnected");
    }
    
    ImGui::SameLine(0, spacing::dp(3));
    
    // Block height
    char heightStr[64];
    snprintf(heightStr, sizeof(heightStr), "Block: %d", m_status.blockHeight);
    Typography::instance().textColored(TypeStyle::Caption, OnSurfaceMedium(), heightStr);
    
    ImGui::SameLine(0, spacing::dp(3));
    
    // Peer count
    char peerStr[32];
    snprintf(peerStr, sizeof(peerStr), "Peers: %d", m_status.peers);
    Typography::instance().textColored(TypeStyle::Caption, OnSurfaceMedium(), peerStr);
    
    // Sync progress (if syncing)
    if (m_status.syncing) {
        ImGui::SameLine(0, spacing::dp(3));
        
        // Mini progress bar
        ImVec2 progressPos = ImGui::GetCursorScreenPos();
        float progressWidth = schema::UI().drawElement("components.main-layout", "sync-bar-width").size;
        float progressHeight = schema::UI().drawElement("components.main-layout", "sync-bar-height").size;
        
        progressPos.y += 6;
        
        // Background
        ImGui::GetWindowDrawList()->AddRectFilled(
            progressPos,
            ImVec2(progressPos.x + progressWidth, progressPos.y + progressHeight),
            ImGui::GetColorU32(Divider()),
            2.0f
        );
        
        // Progress
        ImGui::GetWindowDrawList()->AddRectFilled(
            progressPos,
            ImVec2(progressPos.x + progressWidth * m_status.syncProgress, progressPos.y + progressHeight),
            ImGui::GetColorU32(Primary()),
            2.0f
        );
        
        ImGui::Dummy(ImVec2(progressWidth, 0));
        ImGui::SameLine();
        
        char syncStr[32];
        snprintf(syncStr, sizeof(syncStr), "%.1f%%", m_status.syncProgress * 100.0f);
        ImU32 syncTextColor = IsDarkTheme() ? Primary() : PrimaryVariant();
        Typography::instance().textColored(TypeStyle::Caption, syncTextColor, syncStr);
    }
    
    // Network hashrate (right aligned)
    if (m_status.networkHashrate > 0) {
        char hashrateStr[64];
        if (m_status.networkHashrate > 1e9) {
            snprintf(hashrateStr, sizeof(hashrateStr), "Network: %.2f GH/s", 
                    m_status.networkHashrate / 1e9);
        } else if (m_status.networkHashrate > 1e6) {
            snprintf(hashrateStr, sizeof(hashrateStr), "Network: %.2f MH/s", 
                    m_status.networkHashrate / 1e6);
        } else {
            snprintf(hashrateStr, sizeof(hashrateStr), "Network: %.2f KH/s", 
                    m_status.networkHashrate / 1e3);
        }
        
        ImVec2 textSize = ImGui::CalcTextSize(hashrateStr);
        ImGui::SameLine(windowWidth - textSize.x - spacing::dp(2));
        Typography::instance().textColored(TypeStyle::Caption, OnSurfaceMedium(), hashrateStr);
    }
}

inline void MainLayout::renderSearchOverlay() {
    ImGuiIO& io = ImGui::GetIO();
    float windowWidth = io.DisplaySize.x;
    
    // Search bar at top (below app bar)
    ImGui::SetCursorPos(ImVec2(0, APP_BAR_HEIGHT));
    
    CardSpec cardSpec;
    cardSpec.elevation = 8;
    cardSpec.padding = spacing::dp(2);
    cardSpec.width = windowWidth;
    
    ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(spacing::dp(2), spacing::dp(2)));
    
    if (BeginCard(cardSpec)) {
        ImGui::SetNextItemWidth(windowWidth - spacing::dp(8));
        
        TextFieldSpec textSpec;
        textSpec.placeholder = "Search transactions, addresses...";
        textSpec.variant = TextFieldVariant::Filled;
        textSpec.leadingIcon = ICON_MD_SEARCH;
        textSpec.width = windowWidth - spacing::dp(12);
        
        TextFieldResult result = TextField("global_search", m_searchBuffer, 
                                          sizeof(m_searchBuffer), textSpec);
        
        if (result.submitted && strlen(m_searchBuffer) > 0) {
            if (m_onSearch) m_onSearch(m_searchBuffer);
            m_searchOpen = false;
        }
        
        // Close on escape
        if (ImGui::IsKeyPressed(ImGuiKey_Escape)) {
            m_searchOpen = false;
            memset(m_searchBuffer, 0, sizeof(m_searchBuffer));
        }
        
        EndCard();
    }
    
    ImGui::PopStyleVar();
}

} // namespace screens
} // namespace ui
} // namespace dragonx
