using System.Diagnostics;

namespace Neta.Tray;

public sealed class BackendProcessManager
{
    public static ProcessStartInfo BuildBackendStartInfo(string backendExePath, string traySecret)
    {
        var info = new ProcessStartInfo(backendExePath)
        {
            UseShellExecute = false,
            CreateNoWindow = true,
            WorkingDirectory = Path.GetDirectoryName(backendExePath)!
        };
        info.ArgumentList.Add("--tray-secret");
        info.ArgumentList.Add(traySecret);
        info.ArgumentList.Add("--no-browser");
        return info;
    }

    public Process Start(string backendExePath, string traySecret)
    {
        return Process.Start(BuildBackendStartInfo(backendExePath, traySecret))
            ?? throw new InvalidOperationException("backend.exe 启动失败");
    }

    public bool IsBackendProcessAlive(int pid)
    {
        try
        {
            var process = Process.GetProcessById(pid);
            return !process.HasExited;
        }
        catch
        {
            return false;
        }
    }

    public void WaitForExit(int pid, TimeSpan timeout)
    {
        var deadline = DateTime.UtcNow + timeout;
        while (DateTime.UtcNow < deadline)
        {
            if (!IsBackendProcessAlive(pid)) return;
            Thread.Sleep(200);
        }
    }

    public void KillProcess(int pid)
    {
        try
        {
            var process = Process.GetProcessById(pid);
            if (!process.HasExited)
            {
                process.Kill(true);
                process.WaitForExit(5000);
            }
        }
        catch
        {
        }
    }

    public void KillInstalledBackendProcesses(string backendExePath)
    {
        var normalizedPath = Path.GetFullPath(backendExePath);
        foreach (var process in Process.GetProcessesByName("backend"))
        {
            try
            {
                var fileName = process.MainModule?.FileName;
                if (string.IsNullOrWhiteSpace(fileName)) continue;
                if (!string.Equals(Path.GetFullPath(fileName), normalizedPath, StringComparison.OrdinalIgnoreCase)) continue;
                if (!process.HasExited)
                {
                    process.Kill(true);
                    process.WaitForExit(5000);
                }
            }
            catch
            {
            }
        }
    }
}
