using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using StellaOps.Auth.Abstractions;
using Xunit;

namespace StellaOps.Auth.Abstractions.Tests;

public class StellaOpsProblemResultFactoryTests
{
    [Fact]
    public void AuthenticationRequired_ReturnsCanonicalProblem()
    {
        var result = StellaOpsProblemResultFactory.AuthenticationRequired(instance: "/jobs");

        Assert.Equal(StatusCodes.Status401Unauthorized, result.StatusCode);
        var details = Assert.IsType<ProblemDetails>(result.ProblemDetails);
        Assert.Equal("https://docs.stella-ops.org/problems/authentication-required", details.Type);
        Assert.Equal("Authentication required", details.Title);
        Assert.Equal("/jobs", details.Instance);
        Assert.Equal("unauthorized", details.Extensions["error"]);
        Assert.Equal(details.Detail, details.Extensions["error_description"]);
    }

    [Fact]
    public void InvalidToken_UsesProvidedDetail()
    {
        var result = StellaOpsProblemResultFactory.InvalidToken("expired refresh token");

        var details = Assert.IsType<ProblemDetails>(result.ProblemDetails);
        Assert.Equal(StatusCodes.Status401Unauthorized, result.StatusCode);
        Assert.Equal("expired refresh token", details.Detail);
        Assert.Equal("invalid_token", details.Extensions["error"]);
    }

    [Fact]
    public void InsufficientScope_AddsScopeExtensions()
    {
        var result = StellaOpsProblemResultFactory.InsufficientScope(
            new[] { StellaOpsScopes.FeedserJobsTrigger },
            new[] { StellaOpsScopes.AuthorityUsersManage },
            instance: "/jobs/trigger");

        Assert.Equal(StatusCodes.Status403Forbidden, result.StatusCode);

        var details = Assert.IsType<ProblemDetails>(result.ProblemDetails);
        Assert.Equal("https://docs.stella-ops.org/problems/insufficient-scope", details.Type);
        Assert.Equal("insufficient_scope", details.Extensions["error"]);
        Assert.Equal(new[] { StellaOpsScopes.FeedserJobsTrigger }, Assert.IsType<string[]>(details.Extensions["required_scopes"]));
        Assert.Equal(new[] { StellaOpsScopes.AuthorityUsersManage }, Assert.IsType<string[]>(details.Extensions["granted_scopes"]));
        Assert.Equal("/jobs/trigger", details.Instance);
    }
}
