namespace ClaudeDo.Installer.Core;

public sealed class InstallerService
{
    private readonly IEnumerable<IInstallStep> _steps;

    public InstallerService(IEnumerable<IInstallStep> steps) => _steps = steps;

    public async Task<IReadOnlyList<(IInstallStep Step, StepResult Result)>> ExecuteAsync(
        InstallContext ctx,
        IProgress<StepProgress> progress,
        CancellationToken ct)
    {
        var results = new List<(IInstallStep, StepResult)>();

        foreach (var step in _steps)
        {
            ct.ThrowIfCancellationRequested();
            progress.Report(new StepProgress(step.Name, StepStatus.Running));

            var lineProgress = new Progress<string>(msg =>
                progress.Report(new StepProgress(step.Name, StepStatus.Running, msg)));

            try
            {
                var result = await step.ExecuteAsync(ctx, lineProgress, ct);
                var status = result.Success ? StepStatus.Done : StepStatus.Failed;
                progress.Report(new StepProgress(step.Name, status, result.ErrorMessage));
                results.Add((step, result));

                if (!result.Success) break;
            }
            catch (OperationCanceledException)
            {
                progress.Report(new StepProgress(step.Name, StepStatus.Failed, "Cancelled"));
                results.Add((step, StepResult.Fail("Cancelled")));
                break;
            }
            catch (Exception ex)
            {
                progress.Report(new StepProgress(step.Name, StepStatus.Failed, ex.Message));
                results.Add((step, StepResult.Fail(ex.Message)));
                break;
            }
        }

        return results;
    }
}
