using System.Net;
using System.Text;
using WorkClub.Tests.Integration.Infrastructure;

namespace WorkClub.Tests.Integration.Auth;

public class AuthorizationTests : IntegrationTestBase
{
    public AuthorizationTests(CustomWebApplicationFactory<Program> factory) : base(factory)
    {
    }

    [Fact]
    public async Task AdminCanAccessAdminEndpoints_Returns200()
    {
        AuthenticateAs("admin@test.com", new Dictionary<string, string> { ["club-1"] = "admin" });
        SetTenant("club-1");

        var response = await Client.GetAsync("/health/ready");

        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
    }

    [Fact]
    public async Task MemberCannotAccessAdminEndpoints_Returns403()
    {
        AuthenticateAs("member@test.com", new Dictionary<string, string> { ["club-1"] = "member" });
        SetTenant("club-1");

        var response = await Client.GetAsync("/admin/test");

        Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
    }

    [Fact]
    public async Task ViewerCanOnlyRead_PostReturns403()
    {
        AuthenticateAs("viewer@test.com", new Dictionary<string, string> { ["club-1"] = "viewer" });
        SetTenant("club-1");

        var content = new StringContent("{}", Encoding.UTF8, "application/json");
        var response = await Client.PostAsync("/api/tasks", content);

        Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode);
    }

    [Fact]
    public async Task UnauthenticatedUser_Returns401()
    {
        AuthenticateAsUnauthenticated();

        var response = await Client.GetAsync("/api/tasks");

        Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
    }

    [Fact]
    public async Task HealthEndpointsArePublic_NoAuthRequired()
    {
        AuthenticateAsUnauthenticated();

        var liveResponse = await Client.GetAsync("/health/live");
        var readyResponse = await Client.GetAsync("/health/ready");
        var startupResponse = await Client.GetAsync("/health/startup");

        Assert.Equal(HttpStatusCode.OK, liveResponse.StatusCode);
        Assert.Equal(HttpStatusCode.OK, readyResponse.StatusCode);
        Assert.Equal(HttpStatusCode.OK, startupResponse.StatusCode);
    }
}
