using System.Net;
using System.Net.Http.Json;
using System.Text.Json;
using FluentAssertions;
using Microsoft.Extensions.DependencyInjection;
using StackExchange.Redis;

[Collection("Integration")]
public class RbacTests : IAsyncLifetime
{
    private readonly ApiFixture _fixture;
    private readonly HttpClient _client;

    public RbacTests(ApiFixture fixture)
    {
        _fixture = fixture;
        _client = fixture.CreateClient();
    }

    public async Task InitializeAsync()
    {
        using var scope = _fixture.Services.CreateScope();
        var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
        var redis = scope.ServiceProvider.GetRequiredService<IConnectionMultiplexer>();
        await DbResetHelper.ResetAsync(db);
        await DataSeeder.SeedThresholdsOnlyAsync(db, redis);
    }

    public Task DisposeAsync() => Task.CompletedTask;

    [Fact]
    public async Task Unauthenticated_PatientsList_Returns401()
    {
        _client.ClearAuth();
        var resp = await _client.GetAsync("/api/v1/patients");
        resp.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
    }

    [Fact]
    public async Task Nurse_CannotUpdateThreshold_Returns403()
    {
        _client.ClearAuth();
        _client.AsNurse();

        var listResp = await _client.GetAsync("/api/v1/alert-thresholds");
        listResp.EnsureSuccessStatusCode();
        var thresholds = await listResp.Content.ReadFromJsonAsync<JsonElement>();
        var id = thresholds.GetProperty("data")[0].GetProperty("id").GetGuid();

        var resp = await _client.PutAsJsonAsync($"/api/v1/alert-thresholds/{id}", new
        {
            observationCode = "HEART_RATE",
            displayName = "Heart Rate",
            unit = "/min",
            criticalLow = 40m,
            warningLow = 50m,
            warningHigh = 100m,
            criticalHigh = 130m
        });

        resp.StatusCode.Should().Be(HttpStatusCode.Forbidden);
    }

    [Fact]
    public async Task Admin_CanUpdateThreshold_AndAuditLogCreated()
    {
        _client.ClearAuth();
        _client.AsAdmin();

        var listResp = await _client.GetAsync("/api/v1/alert-thresholds");
        var thresholds = await listResp.Content.ReadFromJsonAsync<JsonElement>();
        var id = thresholds.GetProperty("data")[0].GetProperty("id").GetGuid();

        var resp = await _client.PutAsJsonAsync($"/api/v1/alert-thresholds/{id}", new
        {
            observationCode = "HEART_RATE",
            displayName = "Heart Rate",
            unit = "/min",
            criticalLow = 40m,
            warningLow = 50m,
            warningHigh = 100m,
            criticalHigh = 130m
        });
        resp.EnsureSuccessStatusCode();

        var auditResp = await _client.GetAsync(
            $"/api/v1/audit-logs?entityType=AlertThreshold&entityId={id}");
        auditResp.EnsureSuccessStatusCode();
        var audit = await auditResp.Content.ReadFromJsonAsync<JsonElement>();
        audit.GetProperty("data").GetProperty("totalCount").GetInt32().Should().BeGreaterThan(0);
    }

    [Fact(Skip = "Not yet implemented")]
    public Task AlertAcknowledge_UsesAuthenticatedUser_NotBodyClinicianId()
    {
        _client.ClearAuth();
        var nurseId = Guid.Parse("11111111-1111-1111-1111-111111111111");
        _client.AsNurse(nurseId);

        // ... create patient, encounter, critical observation to generate alert ...
        // ... acknowledge with { "note": "reviewed" } only ...

        // Assert alert.AcknowledgedBy == "Test NURSE" (from TestingAuthHandler display_name)
        // Assert clinical_audit_logs row with action ALERT_ACKNOWLEDGED and userId == nurseId
        return Task.CompletedTask;
    }
}