// 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 "imgui.h"
#include <string>
#include <vector>
#include <functional>

namespace dragonx {
namespace ui {
namespace screens {

using namespace material;

// ============================================================================
// Peers Screen
// ============================================================================
// Display connected peers with Material list

/**
 * @brief Peer connection info
 */
struct PeerInfo {
    int id;
    std::string address;
    std::string subversion;
    int startingHeight;
    int currentHeight;
    int latency;            // ms
    int64_t bytesSent;
    int64_t bytesReceived;
    std::string connTime;   // Connection duration
    bool isInbound;
};

/**
 * @brief Network statistics
 */
struct NetworkStats {
    int totalConnections;
    int inboundCount;
    int outboundCount;
    int64_t totalBytesSent;
    int64_t totalBytesReceived;
    int currentHeight;
    std::string networkName;
};

/**
 * @brief Peers screen with network info
 */
class PeersScreen {
public:
    void setPeers(const std::vector<PeerInfo>& peers) { m_peers = peers; }
    void setNetworkStats(const NetworkStats& stats) { m_networkStats = stats; }
    
    void setOnDisconnectPeer(std::function<void(int peerId)> callback) {
        m_onDisconnectPeer = callback;
    }
    void setOnAddNode(std::function<void(const std::string&)> callback) {
        m_onAddNode = callback;
    }
    
    void render();
    
private:
    void renderNetworkStats();
    void renderPeersList();
    void renderPeerDetails();
    void renderAddNodeDialog();
    
    std::vector<PeerInfo> m_peers;
    NetworkStats m_networkStats;
    
    std::function<void(int)> m_onDisconnectPeer;
    std::function<void(const std::string&)> m_onAddNode;
    
    int m_selectedPeerId = -1;
    bool m_showDetails = false;
    bool m_showAddNode = false;
    char m_addNodeBuffer[256] = {0};
};

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

inline void PeersScreen::render() {
    // Title
    ImGui::BeginGroup();
    {
        Typography::instance().text(TypeStyle::H5, "Network Peers");
        
        ImGui::SameLine(ImGui::GetContentRegionAvail().x - 120);
        
        if (OutlinedButton("+ ADD NODE")) {
            m_showAddNode = true;
        }
    }
    ImGui::EndGroup();
    
    ImGui::Dummy(ImVec2(0, spacing::dp(2)));
    
    // Network stats cards
    renderNetworkStats();
    
    ImGui::Dummy(ImVec2(0, spacing::dp(2)));
    
    // Peers list
    renderPeersList();
    
    // Dialogs
    if (m_showDetails) {
        renderPeerDetails();
    }
    
    if (m_showAddNode) {
        renderAddNodeDialog();
    }
}

inline void PeersScreen::renderNetworkStats() {
    float availWidth = ImGui::GetContentRegionAvail().x;
    float cardWidth = (availWidth - spacing::dp(2) * 3) / 4.0f;
    
    // Connections card
    ImGui::BeginGroup();
    {
        CardSpec cardSpec;
        cardSpec.elevation = 1;
        cardSpec.padding = spacing::dp(2);
        cardSpec.width = cardWidth;
        
        ImGui::PushID("conn_card");
        if (BeginCard(cardSpec)) {
            Typography::instance().textColored(TypeStyle::Overline, OnSurfaceMedium(), "CONNECTIONS");
            ImGui::Dummy(ImVec2(0, spacing::dp(1)));
            
            char connStr[32];
            snprintf(connStr, sizeof(connStr), "%d", m_networkStats.totalConnections);
            Typography::instance().text(TypeStyle::H4, connStr);
            
            char detailStr[64];
            snprintf(detailStr, sizeof(detailStr), ICON_MD_ARROW_DOWNWARD "%d in  " ICON_MD_ARROW_UPWARD "%d out", 
                    m_networkStats.inboundCount, m_networkStats.outboundCount);
            Typography::instance().textColored(TypeStyle::Caption, OnSurfaceMedium(), detailStr);
            
            EndCard();
        }
        ImGui::PopID();
    }
    ImGui::EndGroup();
    
    ImGui::SameLine(0, spacing::dp(2));
    
    // Block height card
    ImGui::BeginGroup();
    {
        CardSpec cardSpec;
        cardSpec.elevation = 1;
        cardSpec.padding = spacing::dp(2);
        cardSpec.width = cardWidth;
        
        ImGui::PushID("height_card");
        if (BeginCard(cardSpec)) {
            Typography::instance().textColored(TypeStyle::Overline, OnSurfaceMedium(), "BLOCK HEIGHT");
            ImGui::Dummy(ImVec2(0, spacing::dp(1)));
            
            char heightStr[32];
            snprintf(heightStr, sizeof(heightStr), "%d", m_networkStats.currentHeight);
            Typography::instance().text(TypeStyle::H4, heightStr);
            
            Typography::instance().textColored(TypeStyle::Caption, OnSurfaceMedium(), 
                                              m_networkStats.networkName.c_str());
            
            EndCard();
        }
        ImGui::PopID();
    }
    ImGui::EndGroup();
    
    ImGui::SameLine(0, spacing::dp(2));
    
    // Data sent card
    ImGui::BeginGroup();
    {
        CardSpec cardSpec;
        cardSpec.elevation = 1;
        cardSpec.padding = spacing::dp(2);
        cardSpec.width = cardWidth;
        
        ImGui::PushID("sent_card");
        if (BeginCard(cardSpec)) {
            Typography::instance().textColored(TypeStyle::Overline, OnSurfaceMedium(), "DATA SENT");
            ImGui::Dummy(ImVec2(0, spacing::dp(1)));
            
            char dataStr[32];
            double mb = m_networkStats.totalBytesSent / (1024.0 * 1024.0);
            if (mb > 1024) {
                snprintf(dataStr, sizeof(dataStr), "%.1f GB", mb / 1024.0);
            } else {
                snprintf(dataStr, sizeof(dataStr), "%.1f MB", mb);
            }
            Typography::instance().text(TypeStyle::H5, dataStr);
            
            EndCard();
        }
        ImGui::PopID();
    }
    ImGui::EndGroup();
    
    ImGui::SameLine(0, spacing::dp(2));
    
    // Data received card
    ImGui::BeginGroup();
    {
        CardSpec cardSpec;
        cardSpec.elevation = 1;
        cardSpec.padding = spacing::dp(2);
        cardSpec.width = cardWidth;
        
        ImGui::PushID("recv_card");
        if (BeginCard(cardSpec)) {
            Typography::instance().textColored(TypeStyle::Overline, OnSurfaceMedium(), "DATA RECEIVED");
            ImGui::Dummy(ImVec2(0, spacing::dp(1)));
            
            char dataStr[32];
            double mb = m_networkStats.totalBytesReceived / (1024.0 * 1024.0);
            if (mb > 1024) {
                snprintf(dataStr, sizeof(dataStr), "%.1f GB", mb / 1024.0);
            } else {
                snprintf(dataStr, sizeof(dataStr), "%.1f MB", mb);
            }
            Typography::instance().text(TypeStyle::H5, dataStr);
            
            EndCard();
        }
        ImGui::PopID();
    }
    ImGui::EndGroup();
}

inline void PeersScreen::renderPeersList() {
    CardSpec cardSpec;
    cardSpec.elevation = 1;
    cardSpec.padding = 0;
    
    if (BeginCard(cardSpec)) {
        if (m_peers.empty()) {
            ImGui::Dummy(ImVec2(0, spacing::dp(4)));
            float availWidth = ImGui::GetContentRegionAvail().x;
            
            const char* emptyText = "No peers connected";
            ImVec2 textSize = ImGui::CalcTextSize(emptyText);
            ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (availWidth - textSize.x) * 0.5f);
            Typography::instance().textColored(TypeStyle::Body1, OnSurfaceMedium(), emptyText);
            
            ImGui::Dummy(ImVec2(0, spacing::dp(4)));
        } else {
            BeginList("peers_list", false);
            
            for (const auto& peer : m_peers) {
                ListItemSpec itemSpec;
                
                // Direction icon
                itemSpec.leadingIcon = peer.isInbound ? ICON_MD_ARROW_DOWNWARD : ICON_MD_ARROW_UPWARD;
                
                // Address as primary
                itemSpec.primaryText = peer.address.c_str();
                
                // Version + latency as secondary
                char secondaryStr[128];
                snprintf(secondaryStr, sizeof(secondaryStr), "%s • %dms • Height: %d",
                        peer.subversion.c_str(), peer.latency, peer.currentHeight);
                itemSpec.secondaryText = secondaryStr;
                
                itemSpec.trailingIcon = ICON_MD_INFO;
                itemSpec.dividerBelow = true;
                
                char peerId[16];
                snprintf(peerId, sizeof(peerId), "peer_%d", peer.id);
                ImGui::PushID(peerId);
                
                if (ListItem(itemSpec)) {
                    m_selectedPeerId = peer.id;
                    m_showDetails = true;
                }
                
                ImGui::PopID();
            }
            
            EndList();
        }
        
        EndCard();
    }
}

inline void PeersScreen::renderPeerDetails() {
    // Find selected peer
    const PeerInfo* selected = nullptr;
    for (const auto& peer : m_peers) {
        if (peer.id == m_selectedPeerId) {
            selected = &peer;
            break;
        }
    }
    
    if (!selected) {
        m_showDetails = false;
        return;
    }
    
    DialogSpec dialogSpec;
    dialogSpec.title = "Peer Details";
    dialogSpec.maxWidth = 450.0f;
    
    DialogResult result = BeginDialog("peer_details", dialogSpec);
    
    if (result.isOpen) {
        const PeerInfo& peer = *selected;
        
        // Direction badge
        ChipSpec chipSpec;
        chipSpec.variant = ChipVariant::Filled;
        chipSpec.color = peer.isInbound ? colors::Blue500 : colors::Orange500;
        Chip(peer.isInbound ? ICON_MD_ARROW_DOWNWARD " Inbound" : ICON_MD_ARROW_UPWARD " Outbound", chipSpec);
        
        ImGui::Dummy(ImVec2(0, spacing::dp(2)));
        
        // Address
        Typography::instance().textColored(TypeStyle::Overline, OnSurfaceMedium(), "ADDRESS");
        Typography::instance().text(TypeStyle::Body1, peer.address.c_str());
        
        ImGui::Dummy(ImVec2(0, spacing::dp(1)));
        
        // Client
        Typography::instance().textColored(TypeStyle::Overline, OnSurfaceMedium(), "CLIENT");
        Typography::instance().text(TypeStyle::Body2, peer.subversion.c_str());
        
        ImGui::Dummy(ImVec2(0, spacing::dp(1)));
        
        // Height
        char heightStr[64];
        snprintf(heightStr, sizeof(heightStr), "%d (started at %d)", 
                peer.currentHeight, peer.startingHeight);
        Typography::instance().textColored(TypeStyle::Overline, OnSurfaceMedium(), "BLOCK HEIGHT");
        Typography::instance().text(TypeStyle::Body2, heightStr);
        
        ImGui::Dummy(ImVec2(0, spacing::dp(1)));
        
        // Latency
        char latencyStr[32];
        snprintf(latencyStr, sizeof(latencyStr), "%d ms", peer.latency);
        Typography::instance().textColored(TypeStyle::Overline, OnSurfaceMedium(), "LATENCY");
        Typography::instance().text(TypeStyle::Body2, latencyStr);
        
        ImGui::Dummy(ImVec2(0, spacing::dp(1)));
        
        // Connected time
        Typography::instance().textColored(TypeStyle::Overline, OnSurfaceMedium(), "CONNECTED");
        Typography::instance().text(TypeStyle::Body2, peer.connTime.c_str());
        
        ImGui::Dummy(ImVec2(0, spacing::dp(1)));
        
        // Data transferred
        char dataStr[64];
        snprintf(dataStr, sizeof(dataStr), ICON_MD_ARROW_UPWARD " %.2f MB  " ICON_MD_ARROW_DOWNWARD " %.2f MB",
                peer.bytesSent / (1024.0 * 1024.0),
                peer.bytesReceived / (1024.0 * 1024.0));
        Typography::instance().textColored(TypeStyle::Overline, OnSurfaceMedium(), "DATA TRANSFERRED");
        Typography::instance().text(TypeStyle::Body2, dataStr);
        
        ImGui::Dummy(ImVec2(0, spacing::dp(3)));
        
        // Actions
        float availWidth = ImGui::GetContentRegionAvail().x;
        
        // Disconnect button (danger)
        ImGui::PushStyleColor(ImGuiCol_Button, colors::withAlpha(colors::Red500, 0.1f));
        ImGui::PushStyleColor(ImGuiCol_ButtonHovered, colors::withAlpha(colors::Red500, 0.2f));
        ImGui::PushStyleColor(ImGuiCol_Text, colors::Red500);
        
        if (ImGui::Button("DISCONNECT", ImVec2(120, 36))) {
            if (m_onDisconnectPeer) m_onDisconnectPeer(peer.id);
            m_showDetails = false;
        }
        
        ImGui::PopStyleColor(3);
        
        ImGui::SameLine(availWidth - 80);
        
        if (ContainedButton("CLOSE")) {
            m_showDetails = false;
        }
        
        EndDialog();
    }
    
    if (result.dismissed) {
        m_showDetails = false;
    }
}

inline void PeersScreen::renderAddNodeDialog() {
    DialogSpec dialogSpec;
    dialogSpec.title = "Add Node";
    dialogSpec.maxWidth = 400.0f;
    
    DialogResult result = BeginDialog("add_node", dialogSpec);
    
    if (result.isOpen) {
        Typography::instance().text(TypeStyle::Body1, 
            "Enter the IP address or hostname of a node to connect to:");
        
        ImGui::Dummy(ImVec2(0, spacing::dp(2)));
        
        TextFieldSpec textSpec;
        textSpec.label = "Node Address";
        textSpec.placeholder = "192.168.1.1:18030 or node.example.com";
        textSpec.variant = TextFieldVariant::Outlined;
        textSpec.width = -1;
        
        TextField("add_node_addr", m_addNodeBuffer, sizeof(m_addNodeBuffer), textSpec);
        
        ImGui::Dummy(ImVec2(0, spacing::dp(3)));
        
        float availWidth = ImGui::GetContentRegionAvail().x;
        ImGui::SetCursorPosX(ImGui::GetCursorPosX() + availWidth - 200);
        
        if (TextButton("CANCEL")) {
            m_showAddNode = false;
            memset(m_addNodeBuffer, 0, sizeof(m_addNodeBuffer));
        }
        
        ImGui::SameLine(0, spacing::dp(2));
        
        bool canAdd = strlen(m_addNodeBuffer) > 0;
        ImGui::BeginDisabled(!canAdd);
        if (ContainedButton("ADD")) {
            if (m_onAddNode) m_onAddNode(m_addNodeBuffer);
            m_showAddNode = false;
            memset(m_addNodeBuffer, 0, sizeof(m_addNodeBuffer));
        }
        ImGui::EndDisabled();
        
        EndDialog();
    }
    
    if (result.dismissed) {
        m_showAddNode = false;
    }
}

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