using HanaTui.System;
using Spectre.Console;
using Spectre.Console.Rendering;

namespace HanaTui.Tui.Components;

/// <summary>
/// Renders the system stats panel (CPU bars, RAM bar, Swap bar, elapsed time).
/// Returns a Spectre.Console IRenderable so it can be embedded in a Live layout.
/// </summary>
public static class StatsPanel
{
    /// <summary>
    /// Build the stats panel renderable from the current snapshot.
    /// </summary>
    public static IRenderable Build(SystemSnapshot snap, TimeSpan elapsed, int panelWidth)
    {
        var barWidth = Math.Max(10, panelWidth - 16); // leave room for label + %

        var grid = new Grid();
        grid.AddColumn(new GridColumn().NoWrap());

        // --- CPU Section ---
        grid.AddRow(new Markup("[bold yellow]CPU[/]"));

        if (snap.CpuPercents.Length == 0)
        {
            grid.AddRow(new Markup("[grey]No data[/]"));
        }
        else
        {
            for (int i = 0; i < snap.CpuPercents.Length; i++)
            {
                var label = snap.CpuLabels.Length > i ? snap.CpuLabels[i] : $"cpu{i}";
                var displayLabel = label == "cpu" ? "Total" : label.Replace("cpu", "Core");
                var pct = snap.CpuPercents[i];
                var bar = BuildBar(pct, barWidth, CpuColor(pct));
                grid.AddRow(new Markup($"  [dim]{displayLabel,-6}[/] {bar} [bold]{pct,5:F1}%[/]"));
            }
        }

        grid.AddRow(new Text(""));

        // --- Memory Section ---
        grid.AddRow(new Markup("[bold cyan]MEMORY[/]"));
        if (snap.MemTotalKb > 0)
        {
            var memPct = snap.MemUsedPercent;
            var memBar = BuildBar(memPct, barWidth, MemColor(memPct));
            grid.AddRow(new Markup(
                $"  [dim]Used  [/] {memBar} [bold]{memPct,5:F1}%[/]"));
            grid.AddRow(new Markup(
                $"  [dim]{SystemSnapshot.FormatGb(snap.MemUsedKb)} / {SystemSnapshot.FormatGb(snap.MemTotalKb)}[/]"));
        }
        else
        {
            grid.AddRow(new Markup("[grey]No data[/]"));
        }

        grid.AddRow(new Text(""));

        // --- Swap Section ---
        grid.AddRow(new Markup("[bold cyan]SWAP[/]"));
        if (snap.SwapTotalKb > 0)
        {
            var swapPct = snap.SwapUsedPercent;
            var swapBar = BuildBar(swapPct, barWidth, MemColor(swapPct));
            grid.AddRow(new Markup(
                $"  [dim]Used  [/] {swapBar} [bold]{swapPct,5:F1}%[/]"));
            grid.AddRow(new Markup(
                $"  [dim]{SystemSnapshot.FormatGb(snap.SwapUsedKb)} / {SystemSnapshot.FormatGb(snap.SwapTotalKb)}[/]"));
        }
        else
        {
            grid.AddRow(new Markup("[grey]No swap[/]"));
        }

        grid.AddRow(new Text(""));

        // --- Elapsed ---
        grid.AddRow(new Markup(
            $"[bold]Elapsed:[/] [yellow]{FormatElapsed(elapsed)}[/]"));

        var panel = new Panel(grid)
        {
            Header = new PanelHeader("[bold] SYSTEM STATS [/]"),
            Border = BoxBorder.Rounded,
            Padding = new Padding(1, 0),
        };

        return panel;
    }

    // -------------------------------------------------------------------------
    // Helpers
    // -------------------------------------------------------------------------

    /// <summary>
    /// Renders a horizontal block bar of the given width.
    /// e.g.  [████████░░░░]
    /// </summary>
    private static string BuildBar(double percent, int width, string color)
    {
        var filled = (int)Math.Round(percent / 100.0 * width);
        filled = Math.Clamp(filled, 0, width);
        var empty = width - filled;

        var bar = new string('\u2588', filled) + new string('\u2591', empty);
        return $"[[{color}]{bar}[/]]";
    }

    private static string CpuColor(double pct) => pct switch
    {
        > 90 => "red",
        > 70 => "yellow",
        > 40 => "green",
        _ => "blue",
    };

    private static string MemColor(double pct) => pct switch
    {
        > 90 => "red",
        > 70 => "yellow",
        _ => "cyan",
    };

    private static string FormatElapsed(TimeSpan t)
    {
        if (t.TotalHours >= 1)
            return $"{(int)t.TotalHours}h {t.Minutes:D2}m {t.Seconds:D2}s";
        if (t.TotalMinutes >= 1)
            return $"{t.Minutes}m {t.Seconds:D2}s";
        return $"{t.Seconds}s";
    }
}
