using System.Runtime.InteropServices;
using System.Text.Json;
using System.Text.RegularExpressions;
using BrikInstaller.Schemas;
using BrikInstaller.Utils;
using Photino.NET;

namespace BrikInstaller.Services;

public static class RequirementsService {
    public static async Task<RequirementCheckingResponse> CheckRequirementsAsync(PhotinoWindow window, string softName) {
        try {
            string requirementsUrl = $"https://brik.azures.fr/products/{softName}/{Constants.Os}-{Constants.Arch}/requirements";
            
            var response = await HttpHelper.FetchAsync(requirementsUrl, HttpMethod.Get);
            
            if (!response.IsSuccessStatusCode) {
                return new RequirementCheckingResponse { Success = false, Status = (int)response.StatusCode };
            }

            string jsonResponse = await response.Content.ReadAsStringAsync();
            var requirements = JsonSerializer.Deserialize<List<ProductRequirement>>(jsonResponse, Constants._jsonOptions);

            if (requirements != null) {
                if (requirements.Count == 0) {
                    return new RequirementCheckingResponse{ Success = true, hasNoDeps = true };
                }
                foreach (var element in requirements) {
                    IPC.sendRequirementCheckConsoleLog(window, $"<span data-i18n=\"log_checking_requirement\"></span><b>{element.Name}</b>");
                    int state = await ProcessRequirement(element);
                    switch (state) {
                        case 0:
                            IPC.sendRequirementCheckConsoleLog(window, $"<span data-i18n=\"log_checking_requirement_error\"></span> <b>{element.Name}</b>");
                            IPC.sendRequirementCheckConsoleLog(window, $"<span data-i18n=\"log_checking_requirement_to_manual_install\"></span><b>{element.Name}</b>");
                            IPC.sendRequirementCheckConsoleLog(window, $"<span data-i18n=\"log_checking_requirement_to_manual_install_1\"></span>");
                            return new RequirementCheckingResponse{ Success = false };
                        case 1:
                            IPC.sendRequirementCheckConsoleLog(window, $"<span data-i18n=\"log_checking_requirement_error\"></span> <b>{element.Name}</b>");
                            IPC.sendRequirementCheckConsoleLog(window, $"<span data-i18n=\"log_checking_requirement_attempt_to_auto_install\"></span><b>{element.Name}</b>");
                            return new RequirementCheckingResponse{ Success = false };
                        case 2:
                            IPC.sendRequirementCheckConsoleLog(window, $"<span data-i18n=\"log_checking_requirement_success\"></span>");
                            break;
                    }
                }
            }
            return new RequirementCheckingResponse{ Success = true };
        } catch (Exception ex) {
            Console.WriteLine($"[RequirementsService] Error: {ex.Message}");
            return new RequirementCheckingResponse{ Success = false, Error = ex.Message };
        }
    }

    public static async Task<int> ProcessRequirement(ProductRequirement requirement) {
        string checkOutput = BashUtils.GetCommandOutput(requirement.CheckCommand!);
        bool isPresent = Regex.IsMatch(checkOutput, requirement.ExpectedOutputPattern!, RegexOptions.IgnoreCase);
        if (!isPresent) {
            bool isAutoinstalled = await RequirementInstallationService.InstallAsync(requirement);
            return isAutoinstalled == true ? 1 : 0;
        } else {
            return 2;
        }
    }
}

public static class RequirementInstallationService {
    public static async Task<bool> InstallAsync(ProductRequirement req) {
        if (string.IsNullOrEmpty(req.InstallationUrl)) return false;

        if (req.InstallationMode == "manual") {
            BashUtils.OpenUrl(req.InstallationUrl);
            return false;
        }

        if (req.InstallationMode == "auto") {
            try {
                var response = await HttpHelper.FetchAsync(req.InstallationUrl);
                if (!response.IsSuccessStatusCode) return false;

                string extension = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".ps1" : ".sh";
                string tempPath = Path.Combine(Path.GetTempPath(), $"brik_install_{req.Id}{extension}");
                
                await File.WriteAllBytesAsync(tempPath, await response.Content.ReadAsByteArrayAsync());

                string cmd = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) 
                    ? $"powershell -ExecutionPolicy Bypass -File \"{tempPath}\"" 
                    : $"chmod +x \"{tempPath}\" && \"{tempPath}\"";

                BashUtils.GetCommandOutput(cmd);
                return true;
            } catch { return false; }
        }

        return false;
    }
}