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

namespace ClaudeDo.Installer.Tests.Checks;

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

    private const string HelpWithAuto =
        "Options:\n  --permission-mode <mode>  Permission mode (choices: \"acceptEdits\", \"auto\", \"bypassPermissions\", \"manual\", \"dontAsk\", \"plan\")\n";

    private const string HelpWithoutAuto =
        "Options:\n  --permission-mode <mode>  Permission mode (choices: \"acceptEdits\", \"bypassPermissions\", \"manual\")\n";

    public PermissionModeAutoCheckTests()
    {
        _dir = Path.Combine(Path.GetTempPath(), $"cdpermmode_{Guid.NewGuid():N}");
        Directory.CreateDirectory(_dir);
        File.WriteAllText(Path.Combine(_dir, "claude.exe"), "");
    }

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

    private ClaudeCliLookup MakeLookup(FakeProcessRunner runner) =>
        new(runner, pathOverride: _dir, pathExtOverride: ".exe");

    [Fact]
    public async Task Auto_listed_in_help_reports_ok()
    {
        var runner = new FakeProcessRunner((0, "2.1.230"), (0, HelpWithAuto));
        var check = new PermissionModeAutoCheck(MakeLookup(runner));

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

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

    [Fact]
    public async Task Auto_missing_from_help_reports_failed_with_hint()
    {
        var runner = new FakeProcessRunner((0, "2.1.230"), (0, HelpWithoutAuto));
        var check = new PermissionModeAutoCheck(MakeLookup(runner));

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

        Assert.Equal(CheckStatus.Failed, result.Status);
        Assert.Equal(CheckSeverity.Warning, result.Severity);
        Assert.NotNull(result.HintKey);
    }

    [Fact]
    public async Task Help_not_determinable_reports_unknown()
    {
        var runner = new FakeProcessRunner((0, "2.1.230"), (1, ""));
        var check = new PermissionModeAutoCheck(MakeLookup(runner));

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

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

    [Fact]
    public async Task Cli_missing_reports_unknown()
    {
        var emptyDir = Path.Combine(Path.GetTempPath(), $"cdpermmode_empty_{Guid.NewGuid():N}");
        Directory.CreateDirectory(emptyDir);
        try
        {
            var runner = new FakeProcessRunner();
            var check = new PermissionModeAutoCheck(new ClaudeCliLookup(runner, pathOverride: emptyDir, pathExtOverride: ".exe"));
            var ctx = new InstallContext { ClaudeBin = "claudedo_totally_missing_cmd_9f3a1" };

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

            Assert.Equal(CheckStatus.Unknown, result.Status);
            Assert.Empty(runner.Calls);
        }
        finally
        {
            Directory.Delete(emptyDir, recursive: true);
        }
    }
}
