using System.Diagnostics;
using System.IO;
using Nexus.Contracts.Apps;
using NexusShell.Models;
using NexusShell.Services.Diagnostics;
using NexusShell.Services.Policy;
using NexusShell.Services.Workspace;

namespace NexusShell.Services;

public enum LaunchResult
{
    Success,
    NotFound,
    Failed,
    Blocked,
}

public sealed class AppLaunchService
{
    private static readonly HashSet<string> NexusHostedAppIds = new(StringComparer.OrdinalIgnoreCase)
    {
        "nexus-browser", "nexus-files", "app-browser", "app-files",
    };

    private readonly AppCatalogService _catalog;
    private readonly ProfileService _profile;
    private readonly LockdownService _lockdown;
    private readonly NexusPolicyService _policy;
    private readonly AppLaunchTracker? _launchTracker;
    private readonly WorkspaceWindowManager? _workspaceWindows;

    public AppLaunchService(
        AppCatalogService catalog,
        ProfileService profile,
        LockdownService lockdown,
        NexusPolicyService policy,
        AppLaunchTracker? launchTracker = null,
        WorkspaceWindowManager? workspaceWindows = null)
    {
        _catalog = catalog;
        _profile = profile;
        _lockdown = lockdown;
        _policy = policy;
        _launchTracker = launchTracker;
        _workspaceWindows = workspaceWindows;
    }

    private static bool IsWindowsSettingsLaunch(AppEntry app)
    {
        var executable = app.ExecutablePath ?? string.Empty;
        var arguments = app.Arguments ?? string.Empty;

        if (executable.Contains("SystemSettings", StringComparison.OrdinalIgnoreCase) ||
            executable.Contains("control.exe", StringComparison.OrdinalIgnoreCase))
        {
            return true;
        }

        return arguments.Contains("ms-settings:", StringComparison.OrdinalIgnoreCase);
    }

    public (LaunchResult Result, string? Message) Launch(string appId)
    {
        var app = _catalog.GetById(appId);
        if (app is null)
        {
            return (LaunchResult.NotFound, "App ikke fundet i katalog");
        }

        return LaunchApp(app);
    }

    public (LaunchResult Result, string? Message) LaunchApp(AppEntry app)
    {
        if (!_policy.CanLaunchApp(app))
        {
            return (LaunchResult.Blocked, null);
        }

        var (decision, lockMessage) = _lockdown.EvaluateLaunch(app);
        if (decision == LockdownDecision.Blocked)
        {
            return (LaunchResult.Blocked, lockMessage ?? "Denne funktion er låst af Ninja Nexus.");
        }

        if (IsWindowsSettingsLaunch(app))
        {
            return (LaunchResult.Blocked,
                "Windows Settings er blokeret. Brug Nexus Settings i stedet.");
        }

        if (NexusHostedAppIds.Contains(app.Id))
        {
            _launchTracker?.TrackLauncherAction("hosted_app_redirect", app.Id);
            return (LaunchResult.Blocked,
                $"{app.Name} skal åbnes via Nexus workspace — ikke som ekstern proces.");
        }

        if (!File.Exists(app.ExecutablePath))
        {
            return (LaunchResult.NotFound, $"Filen findes ikke: {app.ExecutablePath}");
        }

        try
        {
            var startInfo = new ProcessStartInfo
            {
                FileName = app.ExecutablePath,
                Arguments = app.Arguments ?? string.Empty,
                UseShellExecute = true,
            };

            var process = Process.Start(startInfo);
            _profile.AddRecentApp(app.Id);

            if (process is not null && _workspaceWindows is not null)
            {
                _workspaceWindows.RegisterExternalProcess(app.Id, app.Name, process);
            }

            _launchTracker?.TrackExternalLaunch(app.Id, app.Name, process?.Id, process is not null);
            return (LaunchResult.Success, null);
        }
        catch (Exception ex)
        {
            _launchTracker?.TrackExternalLaunch(app.Id, app.Name, null, false, ex.Message);
            return (LaunchResult.Failed, $"Kunne ikke starte {app.Name}: {ex.Message}");
        }
    }
}
