using System.Diagnostics;
using Microsoft.Extensions.Logging;
using PSLauncher.Models;
using SysProcess = System.Diagnostics.Process;

namespace PSLauncher.Core.Process;

public sealed class ProcessLauncher : IProcessLauncher
{
    private readonly ILogger<ProcessLauncher> _logger;

    public ProcessLauncher(ILogger<ProcessLauncher> logger) => _logger = logger;

    public SysProcess Launch(InstalledVersion version, string[]? args = null)
    {
        if (!File.Exists(version.ExecutablePath))
            throw new FileNotFoundException("Executable not found", version.ExecutablePath);

        var psi = new ProcessStartInfo
        {
            FileName = version.ExecutablePath,
            WorkingDirectory = version.FolderPath,
            UseShellExecute = true,
        };

        // Construction MANUELLE de la ligne de commande (via Arguments string),
        // PAS via psi.ArgumentList. Pourquoi : avec UseShellExecute=true, .NET
        // re-sérialise ArgumentList en interne en appliquant un quotage Win32
        // auto qui peut insérer des guillemets inattendus autour des args
        // contenant `=` (cf. bug rapporté : `-login=Jerome` arrivait à Unreal
        // sous une forme que FParse::Value ne reconnaissait pas).
        //
        // En passant Arguments directement, on contrôle au caractère près
        // la ligne de commande effective — c'est la même chaîne qu'aurait
        // produite un .bat avec les mêmes paramètres. Le caller (typiquement
        // `MainViewModel.BuildAutoModeCliArgs`) est responsable du quotage
        // approprié des valeurs avec espaces.
        if (args is not null && args.Length > 0)
        {
            psi.Arguments = string.Join(" ", args);
            _logger.LogInformation("Launching {Exe} with args: {Args}",
                version.ExecutablePath, psi.Arguments);
        }
        else
        {
            _logger.LogInformation("Launching {Exe}", version.ExecutablePath);
        }

        return SysProcess.Start(psi)
               ?? throw new InvalidOperationException("Process.Start returned null");
    }

    public bool IsRunning(InstalledVersion version)
    {
        var name = Path.GetFileNameWithoutExtension(version.ExecutablePath);
        return SysProcess.GetProcessesByName(name).Any(p =>
        {
            try { return string.Equals(p.MainModule?.FileName, version.ExecutablePath, StringComparison.OrdinalIgnoreCase); }
            catch { return false; }
        });
    }
}
