using System.Text.Json;
using ClaudeDo.Installer.Core;

namespace ClaudeDo.Installer.Checks;

/// <summary>
/// Checks login via `claude auth status --json` — never sends a prompt (costs tokens, can hang
/// on a usage-limited account). See docs/explore-notes/installer-preflight.md §4.
/// </summary>
public sealed class ClaudeAuthCheck : IEnvironmentCheck
{
    public const string CheckId = "claude-auth";

    private readonly ClaudeCliLookup _lookup;

    public ClaudeAuthCheck(ClaudeCliLookup lookup)
    {
        _lookup = lookup;
    }

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

    public async Task<CheckResult> RunAsync(InstallContext ctx, CancellationToken ct)
    {
        var lookup = await _lookup.ResolveAsync(ctx, ct);
        if (lookup.Resolved is null)
        {
            return CheckResult.Unknown(Id, Severity, "checks.claudeAuth.title",
                "The claude CLI was not found — login could not be checked.");
        }

        var (fileName, arguments) = ProcessCommand.For(lookup.Resolved, "auth", "status", "--json");
        var (exitCode, output) = await _lookup.ProcessRunner.RunAsync(fileName, arguments, null, ct);

        if (exitCode != 0)
        {
            return CheckResult.Unknown(Id, Severity, "checks.claudeAuth.title",
                "Login status could not be determined.", output);
        }

        var loggedIn = TryParseLoggedIn(output);
        if (loggedIn is null)
        {
            return CheckResult.Unknown(Id, Severity, "checks.claudeAuth.title",
                "Login status could not be determined.", output);
        }

        return loggedIn.Value
            ? CheckResult.Ok(Id, Severity, "checks.claudeAuth.title", "Logged in.")
            : CheckResult.Fail(Id, Severity, "checks.claudeAuth.title", "Not logged in.", "checks.claudeAuth.hint");
    }

    private static bool? TryParseLoggedIn(string output)
    {
        try
        {
            using var doc = JsonDocument.Parse(output);
            if (doc.RootElement.TryGetProperty("loggedIn", out var prop) &&
                prop.ValueKind is JsonValueKind.True or JsonValueKind.False)
            {
                return prop.GetBoolean();
            }
        }
        catch (JsonException)
        {
            // fall through to null — treated as Unknown
        }

        return null;
    }
}
