using System.Management;
using NexusShell.Models;

namespace NexusShell.Services;

public sealed class NexusHardwareService
{
    private readonly NexusDeviceInfoService _deviceInfo;
    private readonly NexusCpuService _cpu;
    private readonly NexusMemoryService _memory;
    private readonly NexusDiskService _disk;
    private readonly NexusGpuService _gpu;
    private readonly NexusNetworkService _network;
    private readonly NexusDisplayService _display;
    private readonly NexusPrinterService _printer;
    private readonly NexusUsbService _usb;
    private readonly NexusBluetoothService _bluetooth;
    private readonly NexusProcessService _process;

    public NexusHardwareService(
        NexusDeviceInfoService deviceInfo,
        NexusCpuService cpu,
        NexusMemoryService memory,
        NexusDiskService disk,
        NexusGpuService gpu,
        NexusNetworkService network,
        NexusDisplayService display,
        NexusPrinterService printer,
        NexusUsbService usb,
        NexusBluetoothService bluetooth,
        NexusProcessService process)
    {
        _deviceInfo = deviceInfo;
        _cpu = cpu;
        _memory = memory;
        _disk = disk;
        _gpu = gpu;
        _network = network;
        _display = display;
        _printer = printer;
        _usb = usb;
        _bluetooth = bluetooth;
        _process = process;
    }

    public NexusDeviceInfoSnapshot CaptureDeviceInfo() => _deviceInfo.Capture();

    public NexusCpuSnapshot CaptureCpu() => _cpu.Capture();

    public NexusMemorySnapshot CaptureMemory() => _memory.Capture();

    public IReadOnlyList<NexusDiskVolumeInfo> GetVolumes() => _disk.GetVolumes();

    public double GetPrimaryFreeGb() => _disk.GetPrimaryFreeGb();

    public NexusGpuSnapshot CaptureGpu() => _gpu.Capture();

    public NexusNetworkSnapshot CaptureNetwork() => _network.Capture();

    public IReadOnlyList<NexusDisplaySnapshot> GetDisplays() => _display.GetDisplays();

    public IReadOnlyList<NexusPrinterInfo> GetPrinters() => _printer.GetPrinters();

    public IReadOnlyList<NexusUsbDeviceInfo> GetUsbDevices() => _usb.GetConnectedDevices();

    public (string Status, IReadOnlyList<NexusBluetoothDeviceInfo> Devices) CaptureBluetooth() =>
        _bluetooth.Capture();

    public IReadOnlyList<NexusProcessInfo> GetTopProcesses() => _process.GetTopProcesses();

    public NexusHardwareOverview CaptureHardwareOverview()
    {
        ReadComputerSystem(out var manufacturer, out var model, out var biosVersion);

        return new NexusHardwareOverview
        {
            MachineName = Environment.MachineName,
            OsLabel = Environment.OSVersion.VersionString,
            BiosVersion = biosVersion,
            SystemManufacturer = manufacturer,
            SystemModel = model,
        };
    }

    public NexusSystemHealthSnapshot CaptureSystemHealth(
        NexusCpuSnapshot cpu,
        NexusMemorySnapshot memory,
        double primaryFreeGb,
        NexusNetworkSnapshot network)
    {
        var cpuLevel = ResolveLevel(cpu.LoadPercent, 75, 90);
        var ramLevel = ResolveLevel(memory.LoadPercent, 80, 92);
        var diskLevel = primaryFreeGb >= 0
            ? ResolveLevelInverse(primaryFreeGb, 20, 10)
            : NexusHealthLevel.Good;
        var networkLevel = network.IsOnline ? NexusHealthLevel.Good : NexusHealthLevel.Warning;

        var levels = new[] { cpuLevel, ramLevel, diskLevel, networkLevel };
        var worst = levels.Max();
        var healthPercent = worst switch
        {
            NexusHealthLevel.Critical => 45,
            NexusHealthLevel.Warning => 72,
            _ => 96,
        };

        return new NexusSystemHealthSnapshot
        {
            OverallStatus = FormatStatus(worst),
            HealthPercent = healthPercent,
            CpuStatus = FormatStatus(cpuLevel),
            RamStatus = FormatStatus(ramLevel),
            DiskStatus = FormatStatus(diskLevel),
            NetworkStatus = FormatStatus(networkLevel),
        };
    }

    private static void ReadComputerSystem(out string manufacturer, out string model, out string biosVersion)
    {
        manufacturer = "—";
        model = "—";
        biosVersion = "—";

        try
        {
            using var system = new ManagementObjectSearcher(
                "SELECT Manufacturer, Model FROM Win32_ComputerSystem");
            foreach (ManagementObject obj in system.Get())
            {
                manufacturer = obj["Manufacturer"]?.ToString()?.Trim() ?? "—";
                model = obj["Model"]?.ToString()?.Trim() ?? "—";
                break;
            }

            using var bios = new ManagementObjectSearcher(
                "SELECT SMBIOSBIOSVersion FROM Win32_BIOS");
            foreach (ManagementObject obj in bios.Get())
            {
                biosVersion = obj["SMBIOSBIOSVersion"]?.ToString()?.Trim() ?? "—";
                break;
            }
        }
        catch
        {
            // WMI unavailable
        }
    }

    private static NexusHealthLevel ResolveLevel(int value, int warning, int critical) =>
        value >= critical ? NexusHealthLevel.Critical :
        value >= warning ? NexusHealthLevel.Warning :
        NexusHealthLevel.Good;

    private static NexusHealthLevel ResolveLevelInverse(double value, double warning, double critical) =>
        value <= critical ? NexusHealthLevel.Critical :
        value <= warning ? NexusHealthLevel.Warning :
        NexusHealthLevel.Good;

    private static string FormatStatus(NexusHealthLevel level) => level switch
    {
        NexusHealthLevel.Critical => "Critical",
        NexusHealthLevel.Warning => "Warning",
        _ => "Good",
    };
}
