using ClaudeDo.Installer.Checks;
using ClaudeDo.Installer.Core;

namespace ClaudeDo.Installer.Tests.Checks;

public sealed class GitIdentityCheckTests : IDisposable
{
    private readonly string _dir;

    public GitIdentityCheckTests()
    {
        _dir = Path.Combine(Path.GetTempPath(), $"cdgitid_{Guid.NewGuid():N}");
        Directory.CreateDirectory(_dir);
    }

    public void Dispose()
    {
        try { Directory.Delete(_dir, recursive: true); } catch { }
    }

    private void MakeGitExe() => File.WriteAllText(Path.Combine(_dir, "git.exe"), "");

    [Fact]
    public async Task Both_set_reports_ok()
    {
        MakeGitExe();
        var runner = new FakeProcessRunner((0, "Mika Kuns\n"), (0, "mika@example.com\n"));
        var check = new GitIdentityCheck(runner, pathOverride: _dir, pathExtOverride: ".exe");

        var result = await check.RunAsync(new InstallContext(), CancellationToken.None);

        Assert.Equal(CheckStatus.Ok, result.Status);
    }

    [Fact]
    public async Task Only_name_set_reports_failed_naming_email()
    {
        MakeGitExe();
        var runner = new FakeProcessRunner((0, "Mika Kuns\n"), (1, ""));
        var check = new GitIdentityCheck(runner, pathOverride: _dir, pathExtOverride: ".exe");

        var result = await check.RunAsync(new InstallContext(), CancellationToken.None);

        Assert.Equal(CheckStatus.Failed, result.Status);
        Assert.Contains("user.email", result.Message);
        Assert.DoesNotContain("user.name", result.Message);
    }

    [Fact]
    public async Task Only_email_set_reports_failed_naming_name()
    {
        MakeGitExe();
        var runner = new FakeProcessRunner((1, ""), (0, "mika@example.com\n"));
        var check = new GitIdentityCheck(runner, pathOverride: _dir, pathExtOverride: ".exe");

        var result = await check.RunAsync(new InstallContext(), CancellationToken.None);

        Assert.Equal(CheckStatus.Failed, result.Status);
        Assert.Contains("user.name", result.Message);
        Assert.DoesNotContain("user.email", result.Message);
    }

    [Fact]
    public async Task Neither_set_reports_failed_naming_both()
    {
        MakeGitExe();
        var runner = new FakeProcessRunner((1, ""), (1, ""));
        var check = new GitIdentityCheck(runner, pathOverride: _dir, pathExtOverride: ".exe");

        var result = await check.RunAsync(new InstallContext(), CancellationToken.None);

        Assert.Equal(CheckStatus.Failed, result.Status);
        Assert.Contains("user.name", result.Message);
        Assert.Contains("user.email", result.Message);
    }

    [Fact]
    public async Task Git_missing_reports_unknown_not_failed()
    {
        var runner = new FakeProcessRunner();
        var check = new GitIdentityCheck(runner, pathOverride: _dir, pathExtOverride: ".exe");

        var result = await check.RunAsync(new InstallContext(), CancellationToken.None);

        Assert.Equal(CheckStatus.Unknown, result.Status);
        Assert.Empty(runner.Calls);
    }
}
