using ClaudeDo.Data.Environment;
using ClaudeDo.Installer.Core;
using ClaudeDo.Installer.Core.Interfaces;

namespace ClaudeDo.Installer.Checks;

/// <summary>Trivial to fix after the fact (git config --global), and the Claude help-me button can resolve it — a warning, not a blocker.</summary>
public sealed class GitIdentityCheck : IEnvironmentCheck
{
    public const string CheckId = "git-identity";

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

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

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

    public async Task<CheckResult> RunAsync(InstallContext ctx, CancellationToken ct)
    {
        var resolved = ExecutableResolver.Resolve("git", _pathOverride, _pathExtOverride);
        if (resolved is null)
        {
            return CheckResult.Unknown(Id, Severity, "checks.gitIdentity.title", "git was not found — identity could not be checked.");
        }

        var name = await ReadConfigAsync(resolved, "user.name", ct);
        var email = await ReadConfigAsync(resolved, "user.email", ct);
        var hasName = !string.IsNullOrWhiteSpace(name);
        var hasEmail = !string.IsNullOrWhiteSpace(email);

        if (hasName && hasEmail)
        {
            return CheckResult.Ok(Id, Severity, "checks.gitIdentity.title", $"{name} <{email}>");
        }

        var missing = (hasName, hasEmail) switch
        {
            (false, false) => "user.name, user.email",
            (false, true) => "user.name",
            _ => "user.email",
        };

        return CheckResult.Fail(Id, Severity, "checks.gitIdentity.title", $"Missing git identity: {missing}.", "checks.gitIdentity.hint");
    }

    private async Task<string> ReadConfigAsync(ResolvedExecutable resolved, string key, CancellationToken ct)
    {
        var (fileName, arguments) = ProcessCommand.For(resolved, "config", "--get", key);
        var (_, output) = await _processRunner.RunAsync(fileName, arguments, null, ct);
        return output.Trim();
    }
}
