using System.Text.RegularExpressions;
using ClaudeDo.Data.Environment;
using ClaudeDo.Installer.Core;
using ClaudeDo.Installer.Core.Interfaces;

namespace ClaudeDo.Installer.Checks;

/// <summary>Without git, no task can run (worktrees) — blocking.</summary>
public sealed class GitCheck : IEnvironmentCheck
{
    public const string CheckId = "git";
    private static readonly Regex VersionPattern = new(@"\d+(\.\d+){1,3}", RegexOptions.Compiled);

    private readonly IProcessRunner _processRunner;
    private readonly string? _pathOverride;
    private readonly string? _pathExtOverride;

    public GitCheck(IProcessRunner processRunner, string? pathOverride = null, string? pathExtOverride = null)
    {
        _processRunner = processRunner;
        _pathOverride = pathOverride;
        _pathExtOverride = pathExtOverride;
    }

    public string Id => CheckId;
    public CheckSeverity Severity => CheckSeverity.Error;

    public async Task<CheckResult> RunAsync(InstallContext ctx, CancellationToken ct)
    {
        var resolved = ExecutableResolver.Resolve("git", _pathOverride, _pathExtOverride);
        if (resolved is null)
        {
            return CheckResult.Fail(Id, Severity, "checks.git.title", "git was not found on PATH.",
                "checks.git.hint", "https://git-scm.com/downloads");
        }

        var (fileName, arguments) = ProcessCommand.For(resolved, "--version");
        var (exitCode, output) = await _processRunner.RunAsync(fileName, arguments, null, ct);

        if (exitCode != 0)
        {
            return CheckResult.Fail(Id, Severity, "checks.git.title", $"'{resolved.Path}' exited with code {exitCode}.",
                "checks.git.hint", "https://git-scm.com/downloads", output);
        }

        var version = VersionPattern.Match(output) is { Success: true } match ? match.Value : output.Trim();
        return CheckResult.Ok(Id, Severity, "checks.git.title", $"{resolved.Path} — {version}");
    }
}
