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

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

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

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

        var patient = new Patient
        {
            Id = Guid.NewGuid(), Mrn = "MRN-T002", FirstName = "Alert", LastName = "Test",
            DateOfBirth = new DateOnly(1980, 6, 15), Gender = "M", CreatedAt = DateTimeOffset.UtcNow
        };
        var encounter = new Encounter
        {
            Id = Guid.NewGuid(), PatientId = patient.Id, EncounterType = EncounterType.Inpatient,
            Status = EncounterStatus.Active, Department = Department.GeneralMedicine,
            AttendingPhysician = "Dr. Test", AdmittedAt = DateTimeOffset.UtcNow,
            CreatedAt = DateTimeOffset.UtcNow
        };
        var alert = new ClinicalAlert
        {
            Id = Guid.NewGuid(), EncounterId = encounter.Id, PatientId = patient.Id,
            AlertType = AlertType.CriticalPotassiumMeqL, Severity = AlertSeverity.Critical,
            Details = "Potassium 2.1 mEq/L is below critical low.", Status = AlertStatus.Open,
            TriggeredAt = DateTimeOffset.UtcNow
        };
        db.Patients.Add(patient);
        db.Encounters.Add(encounter);
        db.ClinicalAlerts.Add(alert);
        await db.SaveChangesAsync();
        _alertId = alert.Id;
    }

    public Task DisposeAsync() => Task.CompletedTask;

    [Fact]
    public async Task AcknowledgeAlert_TransitionsToAcknowledged()
    {
        var resp = await _client.PostAsJsonAsync(
            $"/api/v1/alerts/{_alertId}/acknowledge",
            new AcknowledgeAlertRequest("Reviewing now, ordering repeat labs."));

        resp.StatusCode.Should().Be(HttpStatusCode.OK);
        var body = await resp.Content.ReadFromJsonAsync<JsonDocument>();
        body!.RootElement.GetProperty("data").GetProperty("status").GetString()
            .Should().Be("ACKNOWLEDGED");
        body.RootElement.GetProperty("data").GetProperty("acknowledgedBy").GetString()
            .Should().Be("Test NURSE (NURSE)");
    }

    [Fact]
    public async Task ResolveWithoutAcknowledge_Returns409()
    {
        var resp = await _client.PostAsync($"/api/v1/alerts/{_alertId}/resolve", null);
        resp.StatusCode.Should().Be(HttpStatusCode.Conflict);
        var body = await resp.Content.ReadFromJsonAsync<JsonDocument>();
        body!.RootElement.GetProperty("error").GetProperty("code").GetString()
            .Should().Be("ALERT_NOT_ACKNOWLEDGED");
    }

    [Fact]
    public async Task AcknowledgeThenResolve_FullLifecycle()
    {
        await _client.PostAsJsonAsync(
            $"/api/v1/alerts/{_alertId}/acknowledge",
            new AcknowledgeAlertRequest("Treated."));

        var resolveResp = await _client.PostAsync(
            $"/api/v1/alerts/{_alertId}/resolve", null);

        resolveResp.StatusCode.Should().Be(HttpStatusCode.OK);
        var body = await resolveResp.Content.ReadFromJsonAsync<JsonDocument>();
        body!.RootElement.GetProperty("data").GetProperty("status").GetString()
            .Should().Be("RESOLVED");
    }
}