using System.Globalization;
using System.Runtime.InteropServices;
using NexusShell.Models;

namespace NexusShell.Services;

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

    public NexusMemorySnapshot Capture()
    {
        var status = new MemoryStatusEx { dwLength = (uint)Marshal.SizeOf<MemoryStatusEx>() };
        if (!GlobalMemoryStatusEx(ref status) || status.ullTotalPhys == 0)
        {
            return new NexusMemorySnapshot();
        }

        var totalGb = status.ullTotalPhys / (1024d * 1024 * 1024);
        var freeGb = status.ullAvailPhys / (1024d * 1024 * 1024);
        var usedGb = totalGb - freeGb;

        return new NexusMemorySnapshot
        {
            TotalGb = totalGb,
            UsedGb = usedGb,
            FreeGb = freeGb,
            LoadPercent = (int)Math.Clamp(status.dwMemoryLoad, 0, 100),
        };
    }

    public static string FormatGb(double gb) => $"{gb.ToString("0.#", DaDk)} GB";

    [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;
    }
}
