using ClaudeDo.Installer.Core;

namespace ClaudeDo.Installer.Steps;

public sealed class StartServiceStep : IInstallStep
{
    private const string ServiceName = StopServiceStep.ServiceName;

    public string Name => "Start Worker Service";

    public async Task<StepResult> ExecuteAsync(InstallContext ctx, IProgress<string> progress, CancellationToken ct)
    {
        progress.Report($"Starting {ServiceName}...");

        var (exit, _) = await ProcessRunner.RunAsync("sc.exe", $"start {ServiceName}", null, progress, ct);
        // 1056 = ERROR_SERVICE_ALREADY_RUNNING — fine, fall through to the readiness poll.
        if (exit != 0 && exit != 1056)
            return StepResult.Fail($"sc.exe start failed with exit code {exit}");

        if (exit == 1056)
            progress.Report("Service was already running.");

        // sc.exe start returns as soon as SCM accepts the command. Poll until the
        // service actually reports RUNNING so downstream steps and SignalR clients
        // don't race the worker's startup.
        progress.Report("Waiting for service to reach RUNNING state...");
        for (var i = 0; i < 30; i++)
        {
            ct.ThrowIfCancellationRequested();
            var (q, output) = await ProcessRunner.RunAsync("sc.exe", $"query {ServiceName}", null, progress, ct);
            if (q == 0 && output.Contains("RUNNING", StringComparison.OrdinalIgnoreCase))
                return StepResult.Ok();
            await Task.Delay(1000, ct);
        }

        return StepResult.Fail("Service did not reach RUNNING state within 30 seconds.");
    }
}
