namespace HanaTui.System;

/// <summary>
/// A single snapshot of /proc/stat CPU counters for one CPU line.
/// Used to compute usage % by diffing two samples.
/// </summary>
public readonly struct CpuSample
{
    public readonly string Label;    // "cpu", "cpu0", "cpu1", ...
    public readonly long User;
    public readonly long Nice;
    public readonly long System;
    public readonly long Idle;
    public readonly long IoWait;
    public readonly long Irq;
    public readonly long SoftIrq;
    public readonly long Steal;

    public long Total => User + Nice + System + Idle + IoWait + Irq + SoftIrq + Steal;
    public long Active => Total - Idle - IoWait;

    public CpuSample(string label, long user, long nice, long system,
        long idle, long ioWait, long irq, long softIrq, long steal)
    {
        Label = label;
        User = user;
        Nice = nice;
        System = system;
        Idle = idle;
        IoWait = ioWait;
        Irq = irq;
        SoftIrq = softIrq;
        Steal = steal;
    }

    /// <summary>
    /// Compute usage % between two consecutive samples (0.0 - 100.0).
    /// </summary>
    public static double ComputePercent(CpuSample prev, CpuSample curr)
    {
        var totalDelta = curr.Total - prev.Total;
        var activeDelta = curr.Active - prev.Active;
        if (totalDelta <= 0) return 0.0;
        return Math.Clamp(activeDelta * 100.0 / totalDelta, 0.0, 100.0);
    }

    /// <summary>
    /// Parse all CPU lines from /proc/stat content.
    /// Returns only lines that start with "cpu".
    /// </summary>
    public static List<CpuSample> ParseProcStat(string content)
    {
        var result = new List<CpuSample>();
        foreach (var line in content.Split('\n'))
        {
            if (!line.StartsWith("cpu", StringComparison.Ordinal)) continue;

            var parts = line.Split(' ', StringSplitOptions.RemoveEmptyEntries);
            if (parts.Length < 8) continue;

            result.Add(new CpuSample(
                label:   parts[0],
                user:    long.TryParse(parts[1], out var u) ? u : 0,
                nice:    long.TryParse(parts[2], out var n) ? n : 0,
                system:  long.TryParse(parts[3], out var s) ? s : 0,
                idle:    long.TryParse(parts[4], out var id) ? id : 0,
                ioWait:  long.TryParse(parts[5], out var io) ? io : 0,
                irq:     long.TryParse(parts[6], out var irq) ? irq : 0,
                softIrq: long.TryParse(parts[7], out var si) ? si : 0,
                steal:   parts.Length > 8 && long.TryParse(parts[8], out var st) ? st : 0
            ));
        }
        return result;
    }
}
