using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using NexusShell.Models;

namespace NexusShell.Services;

public sealed class NexusDeviceInfoService
{
    private static readonly CultureInfo DaDk = CultureInfo.GetCultureInfo("da-DK");

    public NexusDeviceInfoSnapshot Capture()
    {
        return new NexusDeviceInfoSnapshot
        {
            CpuName = ReadCpuName(),
            RamLabel = ReadRamLabel(),
            DiskLabel = ReadDiskLabel(),
            GpuName = ReadGpuName(),
        };
    }

    private static string ReadCpuName()
    {
        try
        {
            using var key = Registry.LocalMachine.OpenSubKey(@"HARDWARE\DESCRIPTION\System\CentralProcessor\0");
            var name = key?.GetValue("ProcessorNameString") as string;
            return string.IsNullOrWhiteSpace(name) ? "Ukendt processor" : name.Trim();
        }
        catch
        {
            return "Ukendt processor";
        }
    }

    private static string ReadRamLabel()
    {
        var status = new MemoryStatusEx { dwLength = (uint)Marshal.SizeOf<MemoryStatusEx>() };
        if (!GlobalMemoryStatusEx(ref status) || status.ullTotalPhys == 0)
        {
            return "—";
        }

        var totalGb = status.ullTotalPhys / (1024d * 1024 * 1024);
        return $"{totalGb.ToString("0.#", DaDk)} GB RAM";
    }

    private static string ReadDiskLabel()
    {
        try
        {
            var drive = DriveInfo.GetDrives()
                .FirstOrDefault(static d => d is { IsReady: true, DriveType: DriveType.Fixed });
            if (drive is null)
            {
                return "—";
            }

            var totalGb = drive.TotalSize / (1024d * 1024 * 1024);
            var freeGb = drive.AvailableFreeSpace / (1024d * 1024 * 1024);
            return $"{drive.Name.TrimEnd('\\')} — {freeGb.ToString("0.#", DaDk)} / {totalGb.ToString("0.#", DaDk)} GB ledig";
        }
        catch
        {
            return "—";
        }
    }

    private static string ReadGpuName()
    {
        try
        {
            using var key = Registry.LocalMachine.OpenSubKey(
                @"SYSTEM\CurrentControlSet\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}");
            if (key is null)
            {
                return "Ukendt grafik";
            }

            foreach (var subKeyName in key.GetSubKeyNames())
            {
                using var sub = key.OpenSubKey(subKeyName);
                var desc = sub?.GetValue("DriverDesc") as string;
                if (!string.IsNullOrWhiteSpace(desc))
                {
                    return desc.Trim();
                }
            }
        }
        catch
        {
            // POC: ignore
        }

        return "Ukendt grafik";
    }

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool GlobalMemoryStatusEx(ref MemoryStatusEx status);

    [StructLayout(LayoutKind.Sequential)]
    private struct MemoryStatusEx
    {
        public uint dwLength;
        public uint dwMemoryLoad;
        public ulong ullTotalPhys;
        public ulong ullAvailPhys;
        public ulong ullTotalPageFile;
        public ulong ullAvailPageFile;
        public ulong ullTotalVirtual;
        public ulong ullAvailVirtual;
        public ulong ullAvailExtendedVirtual;
    }
}
