using ITNexusAgent.Models;
using System.Diagnostics;
using System.Management;
using System.Net;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using System.Security.Principal;
using Microsoft.Win32;

namespace ITNexusAgent.Services;

public static class SystemInfoService
{
    public static string GetHostname() => Environment.MachineName;

    public static string GetDomain() =>
        Environment.UserDomainName != Environment.MachineName
            ? Environment.UserDomainName
            : "";

    public static string GetOs()
    {
        try
        {
            using var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");
            var name = key?.GetValue("ProductName")?.ToString() ?? "Windows";
            var build = key?.GetValue("CurrentBuildNumber")?.ToString();
            var ubr = key?.GetValue("UBR")?.ToString();

            // Build >= 22000 = Windows 11 — Registry ProductName kann noch "Windows 10" sagen nach Upgrade
            if (build != null && int.TryParse(build, out var buildNum) && buildNum >= 22000)
                name = name.Replace("Windows 10", "Windows 11");

            return build != null ? $"{name} (Build {build}.{ubr})" : name;
        }
        catch { return RuntimeInformation.OSDescription; }
    }

    public static string GetOsVersion()
    {
        try
        {
            using var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");
            return key?.GetValue("CurrentBuildNumber")?.ToString() ?? Environment.OSVersion.Version.ToString();
        }
        catch { return Environment.OSVersion.Version.ToString(); }
    }

    public static string GetIpAddress()
    {
        try
        {
            foreach (var iface in NetworkInterface.GetAllNetworkInterfaces())
            {
                if (iface.OperationalStatus != OperationalStatus.Up) continue;
                if (iface.NetworkInterfaceType == NetworkInterfaceType.Loopback) continue;
                var name = iface.Name.ToLower();
                if (name.Contains("virtual") || name.Contains("wsl") || name.Contains("vmware")) continue;

                foreach (var addr in iface.GetIPProperties().UnicastAddresses)
                {
                    if (addr.Address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork) continue;
                    var ip = addr.Address.ToString();
                    if (ip.StartsWith("169.254") || ip.StartsWith("172.")) continue;
                    return ip;
                }
            }
        }
        catch { }
        return "";
    }

    public static string GetMacAddress()
    {
        try
        {
            foreach (var iface in NetworkInterface.GetAllNetworkInterfaces())
            {
                if (iface.OperationalStatus != OperationalStatus.Up) continue;
                if (iface.NetworkInterfaceType == NetworkInterfaceType.Loopback) continue;
                var mac = iface.GetPhysicalAddress().ToString();
                if (mac.Length == 12)
                    return string.Join(":", Enumerable.Range(0, 6).Select(i => mac.Substring(i * 2, 2)));
            }
        }
        catch { }
        return "";
    }

    public static string GetLastUser()
    {
        try
        {
            using var searcher = new ManagementObjectSearcher("SELECT UserName FROM Win32_ComputerSystem");
            foreach (ManagementObject obj in searcher.Get())
            {
                var user = obj["UserName"]?.ToString();
                if (!string.IsNullOrEmpty(user))
                    return user.Contains('\\') ? user.Split('\\')[1] : user;
            }
            // Fallback: letztes Profil
            using var key = Registry.LocalMachine.OpenSubKey(
                @"SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI");
            return key?.GetValue("LastLoggedOnUser")?.ToString()?.Split('\\').LastOrDefault() ?? "";
        }
        catch { return ""; }
    }

    public static (string Model, int Cores) GetCpuInfo()
    {
        try
        {
            using var searcher = new ManagementObjectSearcher("SELECT Name, NumberOfCores FROM Win32_Processor");
            foreach (ManagementObject obj in searcher.Get())
                return (obj["Name"]?.ToString()?.Trim() ?? "", Convert.ToInt32(obj["NumberOfCores"]));
        }
        catch { }
        return ("", 0);
    }

    public static double GetCpuUsage()
    {
        try
        {
            using var counter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
            counter.NextValue();
            Thread.Sleep(800);
            return Math.Round(counter.NextValue(), 1);
        }
        catch { return 0; }
    }

    public static (double Total, double Used) GetRamInfo()
    {
        try
        {
            using var searcher = new ManagementObjectSearcher("SELECT TotalVisibleMemorySize, FreePhysicalMemory FROM Win32_OperatingSystem");
            foreach (ManagementObject obj in searcher.Get())
            {
                var total = Math.Round(Convert.ToDouble(obj["TotalVisibleMemorySize"]) / (1024 * 1024), 2);
                var free = Math.Round(Convert.ToDouble(obj["FreePhysicalMemory"]) / (1024 * 1024), 2);
                return (total, Math.Round(total - free, 2));
            }
        }
        catch { }
        return (0, 0);
    }

    public static (double Total, double Free) GetDiskInfo()
    {
        try
        {
            var drive = new DriveInfo("C");
            return (
                Math.Round(drive.TotalSize / (double)(1024 * 1024 * 1024), 2),
                Math.Round(drive.AvailableFreeSpace / (double)(1024 * 1024 * 1024), 2)
            );
        }
        catch { return (0, 0); }
    }

    public static double GetUptimeHours()
    {
        try
        {
            var uptime = TimeSpan.FromMilliseconds(Environment.TickCount64);
            return Math.Round(uptime.TotalHours, 1);
        }
        catch { return 0; }
    }

    public static int GetPendingUpdates()
    {
        try
        {
            var type = Type.GetTypeFromProgID("Microsoft.Update.Session");
            if (type == null) return 0;
            dynamic session = Activator.CreateInstance(type)!;
            var searcher = session.CreateUpdateSearcher();
            var result = searcher.Search("IsInstalled=0 and Type='Software'");
            return result.Updates.Count;
        }
        catch { return 0; }
    }

    public static (bool Present, string Version, bool V2) GetTpmInfo()
    {
        try
        {
            using var searcher = new ManagementObjectSearcher(@"root\CIMv2\Security\MicrosoftTpm",
                "SELECT * FROM Win32_Tpm");
            foreach (ManagementObject obj in searcher.Get())
            {
                var version = obj["SpecVersion"]?.ToString() ?? "";
                return (true, version, version.StartsWith("2.0"));
            }
        }
        catch { }
        return (false, "", false);
    }

    public static bool GetSecureBoot()
    {
        try
        {
            using var key = Registry.LocalMachine.OpenSubKey(
                @"SYSTEM\CurrentControlSet\Control\SecureBoot\State");
            return Convert.ToInt32(key?.GetValue("UEFISecureBootEnabled") ?? 0) == 1;
        }
        catch { return false; }
    }

    public static bool GetWin11Readiness(bool tpmV2, bool secureBoot, int cpuCores, double ramGb)
    {
        // Wenn bereits Win 11 läuft → immer true
        try
        {
            using var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");
            var build = key?.GetValue("CurrentBuildNumber")?.ToString();
            if (build != null && int.TryParse(build, out var b) && b >= 22000) return true;
        }
        catch { }
        return tpmV2 && secureBoot && cpuCores >= 2 && ramGb >= 4;
    }

    public static string GetHardwareSerial()
    {
        try
        {
            using var searcher = new ManagementObjectSearcher("SELECT SerialNumber FROM Win32_BIOS");
            foreach (ManagementObject obj in searcher.Get())
                return obj["SerialNumber"]?.ToString()?.Trim() ?? "";
        }
        catch { }
        return "";
    }

    public static List<string> GetInstalledSoftware()
    {
        var apps = new HashSet<string>();
        var paths = new[]
        {
            @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
            @"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
        };

        foreach (var path in paths)
        {
            try
            {
                using var key = Registry.LocalMachine.OpenSubKey(path);
                if (key == null) continue;
                foreach (var subName in key.GetSubKeyNames())
                {
                    using var sub = key.OpenSubKey(subName);
                    var name = sub?.GetValue("DisplayName")?.ToString();
                    if (string.IsNullOrWhiteSpace(name)) continue;
                    if (System.Text.RegularExpressions.Regex.IsMatch(name, @"^KB\d+")) continue;
                    apps.Add(name.Trim());
                }
            }
            catch { }
        }

        return [.. apps.OrderBy(x => x).Take(100)];
    }
}
