using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.ServiceProcess;

namespace ZB.MOM.WW.OtOpcUa.Driver.Galaxy.TestSupport.Probes;

/// <summary>
///     Queries the Windows Service Control Manager to report whether a named service is
///     installed, its current state, and its start type. Non-Windows hosts return Skip.
/// </summary>
public static class ServiceProbe
{
    public static PrerequisiteCheck Check(
        string serviceName,
        PrerequisiteCategory category,
        bool hardRequired,
        string whatItDoes)
    {
        if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
        {
            return new PrerequisiteCheck(
                Name: $"service:{serviceName}",
                Category: category,
                Status: PrerequisiteStatus.Skip,
                Detail: "Service probes only run on Windows.");
        }

        return CheckWindows(serviceName, category, hardRequired, whatItDoes);
    }

    [SupportedOSPlatform("windows")]
    private static PrerequisiteCheck CheckWindows(
        string serviceName, PrerequisiteCategory category, bool hardRequired, string whatItDoes)
    {
        try
        {
            using var sc = new ServiceController(serviceName);
            // Touch the Status to force the SCM lookup; if the service doesn't exist, this throws
            // InvalidOperationException with message "Service ... was not found on computer.".
            var status = sc.Status;
            var startType = sc.StartType;

            return status switch
            {
                ServiceControllerStatus.Running => new PrerequisiteCheck(
                    $"service:{serviceName}", category, PrerequisiteStatus.Pass,
                    $"Running ({whatItDoes})"),

                // DemandStart services (like NmxSvc) that are Stopped are not necessarily a
                // failure — the master service (aaBootstrap) brings them up on demand. Treat
                // Stopped+Demand as Warn so operators know the situation but tests still proceed.
                ServiceControllerStatus.Stopped when startType == ServiceStartMode.Manual =>
                    new PrerequisiteCheck(
                        $"service:{serviceName}", category, PrerequisiteStatus.Warn,
                        $"Installed but Stopped (start type Manual — {whatItDoes}). " +
                        "Will be pulled up on demand by the master service; fine for tests."),

                ServiceControllerStatus.Stopped => Fail(
                    $"Installed but Stopped. Start with: sc.exe start {serviceName}  ({whatItDoes})"),

                _ => new PrerequisiteCheck(
                    $"service:{serviceName}", category, PrerequisiteStatus.Warn,
                    $"Transitional state {status} ({whatItDoes}) — try again in a few seconds."),
            };

            PrerequisiteCheck Fail(string detail) => new(
                $"service:{serviceName}", category,
                hardRequired ? PrerequisiteStatus.Fail : PrerequisiteStatus.Warn,
                detail);
        }
        catch (InvalidOperationException ex) when (ex.Message.Contains("was not found", StringComparison.OrdinalIgnoreCase))
        {
            return new PrerequisiteCheck(
                $"service:{serviceName}", category,
                hardRequired ? PrerequisiteStatus.Fail : PrerequisiteStatus.Warn,
                $"Not installed ({whatItDoes}). Install the relevant System Platform component and retry.");
        }
        catch (Exception ex)
        {
            return new PrerequisiteCheck(
                $"service:{serviceName}", category, PrerequisiteStatus.Warn,
                $"Probe failed ({ex.GetType().Name}: {ex.Message}) — treat as unknown.");
        }
    }
}
