using System.Diagnostics;

namespace ZB.MOM.WW.MxGateway.Server.Workers;

/// <summary>
///     <see cref="IRunningProcessInspector"/> backed by <see cref="Process"/>.
/// </summary>
public sealed class SystemRunningProcessInspector : IRunningProcessInspector
{
    /// <inheritdoc />
    public IReadOnlyList<RunningProcessInfo> GetProcessesByName(string processName)
    {
        List<RunningProcessInfo> results = [];
        Process[] processes = Process.GetProcessesByName(processName);
        try
        {
            foreach (Process process in processes)
            {
                results.Add(new RunningProcessInfo(process.Id, TryGetExecutablePath(process)));
            }
        }
        finally
        {
            foreach (Process process in processes)
            {
                process.Dispose();
            }
        }

        return results;
    }

    /// <inheritdoc />
    public void Kill(int processId)
    {
        using Process process = Process.GetProcessById(processId);
        process.Kill(entireProcessTree: true);
    }

    private static string? TryGetExecutablePath(Process process)
    {
        try
        {
            return process.MainModule?.FileName;
        }
        catch (Exception exception) when (exception is InvalidOperationException
            or System.ComponentModel.Win32Exception
            or NotSupportedException)
        {
            // Access to the main module can be denied (e.g. a 64-bit gateway
            // querying a 32-bit worker, or a process owned by another user).
            return null;
        }
    }
}
