using System.Diagnostics;

using System.Net.Http;

using NexusInstaller.Models;



namespace NexusInstaller.Services;



internal static class SystemRequirementsService

{

    private const long MinimumFreeBytes = 500L * 1024 * 1024;

    private const string UpdateChannelUrl = "https://nexus.ninjakernen.info/downloads/latest.json";



    public static async Task<IReadOnlyList<RequirementCheck>> EvaluateAsync(string installRoot)

    {

        var localAppDataRoot = Path.Combine(

            Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),

            "NinjaNexus");



        var checks = new List<RequirementCheck>

        {

            await CheckDotNet8DesktopAsync(),

            await CheckDotNet10DesktopAsync(),

            CheckWebView2(),

            CheckVcRedist(),

            await CheckUpdateChannelAsync(),

            await CheckNetworkAsync(),

            CheckDiskSpace(installRoot),

            CheckWritePermission(installRoot, "Installationsmappe", PrerequisiteKind.WriteInstallPath),

            CheckWritePermission(localAppDataRoot, "NinjaNexus AppData", PrerequisiteKind.WriteLocalAppData),

            CheckAdminElevation(),
            CheckWindowsVersion(),

        };



        return checks;

    }



    public static bool HasBlockingIssues(IReadOnlyList<RequirementCheck> checks) =>

        checks.Any(c => c.Status == RequirementStatus.Missing && !c.IsAutoInstallable);



    public static bool HasAutoInstallPending(IReadOnlyList<RequirementCheck> checks) =>

        checks.Any(c => c.Status == RequirementStatus.Missing && c.IsAutoInstallable);



    private static async Task<RequirementCheck> CheckDotNet8DesktopAsync()

    {

        var installed = await RuntimeChecker.HasDotNet8DesktopAsync();

        return new RequirementCheck

        {

            Kind = PrerequisiteKind.DotNet8Desktop,

            Label = ".NET 8 Desktop Runtime",

            Status = installed ? RequirementStatus.Ok : RequirementStatus.Missing,

            Detail = installed ? "Microsoft.WindowsDesktop.App 8.x fundet" : "Kræves til Nexus Shell",

        };

    }



    private static async Task<RequirementCheck> CheckDotNet10DesktopAsync()

    {

        var installed = await RuntimeChecker.HasDotNet10DesktopAsync();

        return new RequirementCheck

        {

            Kind = PrerequisiteKind.DotNet10Desktop,

            Label = ".NET 10 Desktop Runtime",

            Status = installed ? RequirementStatus.Ok : RequirementStatus.Missing,

            Detail = installed ? "Microsoft.WindowsDesktop.App 10.x fundet" : "Kræves til fremtidige Nexus-komponenter",

        };

    }



    private static RequirementCheck CheckWebView2()

    {

        var installed = PrerequisiteService.IsWebView2Installed();

        return new RequirementCheck

        {

            Kind = PrerequisiteKind.WebView2,

            Label = "WebView2 Runtime",

            Status = installed ? RequirementStatus.Ok : RequirementStatus.Missing,

            Detail = installed ? "Microsoft Edge WebView2 fundet" : "Kræves til indlejrede webvisninger",

        };

    }



    private static RequirementCheck CheckVcRedist()

    {

        var installed = PrerequisiteService.IsVcRedistInstalled();

        return new RequirementCheck

        {

            Kind = PrerequisiteKind.VcRedist,

            Label = "Visual C++ Redistributable (x64)",

            Status = installed ? RequirementStatus.Ok : RequirementStatus.Missing,

            Detail = installed ? "VC++ 2015-2022 x64 fundet" : "Kræves af nogle native komponenter",

        };

    }



    private static RequirementCheck CheckDiskSpace(string installRoot)

    {

        try

        {

            var root = Path.GetPathRoot(Path.GetFullPath(installRoot)) ?? "C:\\";

            var drive = new DriveInfo(root);

            if (drive.AvailableFreeSpace >= MinimumFreeBytes)

            {

                var gb = drive.AvailableFreeSpace / (1024.0 * 1024 * 1024);

                return new RequirementCheck

                {

                    Kind = PrerequisiteKind.DiskSpace,

                    Label = "Diskplads",

                    Status = RequirementStatus.Ok,

                    Detail = $"{gb:F1} GB ledig på {root.TrimEnd('\\')}",

                };

            }



            return new RequirementCheck

            {

                Kind = PrerequisiteKind.DiskSpace,

                Label = "Diskplads",

                Status = RequirementStatus.Missing,

                Detail = "Mindst 500 MB ledig plads kræves",

            };

        }

        catch (Exception ex)

        {

            return new RequirementCheck

            {

                Kind = PrerequisiteKind.DiskSpace,

                Label = "Diskplads",

                Status = RequirementStatus.Warning,

                Detail = ex.Message,

            };

        }

    }



    private static RequirementCheck CheckAdminElevation()
    {
        var elevated = AdminElevationHelper.IsRunningElevated();
        return new RequirementCheck
        {
            Kind = PrerequisiteKind.AdminElevation,
            Label = "Admin/elevation",
            Status = elevated ? RequirementStatus.Ok : RequirementStatus.Warning,
            Detail = elevated
                ? "Setup kører med administratorrettigheder"
                : "Kræves ved installation. Brug 'Genstart som administrator'.",
        };
    }
    private static RequirementCheck CheckWindowsVersion()

    {

        var version = Environment.OSVersion.Version;

        if (version.Major >= 10)

        {

            return new RequirementCheck

            {

                Kind = PrerequisiteKind.WindowsVersion,

                Label = "Windows-version",

                Status = RequirementStatus.Ok,

                Detail = $"Windows {version.Major}.{version.Build}",

            };

        }



        return new RequirementCheck

        {

            Kind = PrerequisiteKind.WindowsVersion,

            Label = "Windows-version",

            Status = RequirementStatus.Missing,

            Detail = "Windows 10 eller nyere kræves",

        };

    }



    private static RequirementCheck CheckWritePermission(string targetPath, string label, PrerequisiteKind kind)

    {

        try

        {

            Directory.CreateDirectory(targetPath);

            var probe = Path.Combine(targetPath, $".nexus-write-{Guid.NewGuid():N}.tmp");

            File.WriteAllText(probe, "ok");

            File.Delete(probe);

            return new RequirementCheck

            {

                Kind = kind,

                Label = label,

                Status = RequirementStatus.Ok,

                Detail = "Skrivetilladelse OK",

            };

        }

        catch (Exception ex)

        {

            return new RequirementCheck

            {

                Kind = kind,

                Label = label,

                Status = RequirementStatus.Missing,

                Detail = ex.Message,

            };

        }

    }



    private static async Task<RequirementCheck> CheckUpdateChannelAsync()

    {

        try

        {

            using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(8) };

            using var response = await http.GetAsync(UpdateChannelUrl);

            if (response.IsSuccessStatusCode)

            {

                return new RequirementCheck

                {

                    Kind = PrerequisiteKind.UpdateChannel,

                    Label = "Nexus update channel",

                    Status = RequirementStatus.Ok,

                    Detail = "nexus.ninjakernen.info er tilgængelig",

                };

            }



            return new RequirementCheck

            {

                Kind = PrerequisiteKind.UpdateChannel,

                Label = "Nexus update channel",

                Status = RequirementStatus.Warning,

                Detail = $"HTTP {(int)response.StatusCode}",

            };

        }

        catch (Exception ex)

        {

            return new RequirementCheck

            {

                Kind = PrerequisiteKind.UpdateChannel,

                Label = "Nexus update channel",

                Status = RequirementStatus.Warning,

                Detail = ex.Message,

            };

        }

    }



    private static async Task<RequirementCheck> CheckNetworkAsync()

    {

        try

        {

            using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(6) };

            using var response = await http.GetAsync("https://www.microsoft.com", HttpCompletionOption.ResponseHeadersRead);

            return new RequirementCheck

            {

                Kind = PrerequisiteKind.Network,

                Label = "Netværksforbindelse",

                Status = response.IsSuccessStatusCode ? RequirementStatus.Ok : RequirementStatus.Missing,

                Detail = response.IsSuccessStatusCode ? "Internetforbindelse OK" : "Ingen netværksforbindelse",

            };

        }

        catch (Exception ex)

        {

            return new RequirementCheck

            {

                Kind = PrerequisiteKind.Network,

                Label = "Netværksforbindelse",

                Status = RequirementStatus.Missing,

                Detail = ex.Message,

            };

        }

    }



    public static void OpenDotNetDownload()

    {

        Process.Start(new ProcessStartInfo

        {

            FileName = "https://dotnet.microsoft.com/download/dotnet/10.0",

            UseShellExecute = true,

        });

    }

}


