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 EncountersListTests : IAsyncLifetime
{
    private readonly ApiFixture _fixture;
    private readonly HttpClient _client;
    private Guid _activeIcuEncounterId;
    private Guid _activeSurgeryEncounterId;
    private Guid _dischargedEncounterId;

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

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

        var patientIcu = new Patient
        {
            Id = Guid.NewGuid(), Mrn = "MRN-WARD-001", FirstName = "Alice", LastName = "Icu",
            DateOfBirth = new DateOnly(1970, 3, 1), Gender = "F", CreatedAt = DateTimeOffset.UtcNow
        };
        var patientSurgery = new Patient
        {
            Id = Guid.NewGuid(), Mrn = "MRN-WARD-002", FirstName = "Bob", LastName = "Surgery",
            DateOfBirth = new DateOnly(1965, 7, 12), Gender = "M", CreatedAt = DateTimeOffset.UtcNow
        };

        _activeIcuEncounterId = Guid.NewGuid();
        _activeSurgeryEncounterId = Guid.NewGuid();
        _dischargedEncounterId = Guid.NewGuid();

        db.Patients.AddRange(patientIcu, patientSurgery);
        db.Encounters.AddRange(
            new Encounter
            {
                Id = _activeIcuEncounterId, PatientId = patientIcu.Id,
                EncounterType = EncounterType.Inpatient, Status = EncounterStatus.Active,
                Department = Department.Icu, AttendingPhysician = "Dr. Ward",
                RoomBed = "ICU-3", AdmittedAt = DateTimeOffset.UtcNow.AddHours(-2),
                CreatedAt = DateTimeOffset.UtcNow
            },
            new Encounter
            {
                Id = _activeSurgeryEncounterId, PatientId = patientSurgery.Id,
                EncounterType = EncounterType.Inpatient, Status = EncounterStatus.Active,
                Department = Department.Surgery, AttendingPhysician = "Dr. Ward",
                RoomBed = "S-12", AdmittedAt = DateTimeOffset.UtcNow.AddHours(-1),
                CreatedAt = DateTimeOffset.UtcNow
            },
            new Encounter
            {
                Id = _dischargedEncounterId, PatientId = patientSurgery.Id,
                EncounterType = EncounterType.Outpatient, Status = EncounterStatus.Discharged,
                Department = Department.Surgery, AttendingPhysician = "Dr. Ward",
                AdmittedAt = DateTimeOffset.UtcNow.AddDays(-3),
                DischargedAt = DateTimeOffset.UtcNow.AddDays(-2),
                CreatedAt = DateTimeOffset.UtcNow.AddDays(-3)
            });

        db.News2Scores.Add(new News2Score
        {
            Id = Guid.NewGuid(), EncounterId = _activeIcuEncounterId, PatientId = patientIcu.Id,
            TotalScore = 7, RiskLevel = "HIGH", CalculatedAt = DateTimeOffset.UtcNow,
            RespRateScore = 1, Spo2Score = 0, SystolicBpScore = 1, HeartRateScore = 1,
            ConsciousnessScore = 0, TemperatureScore = 0, SupplementalO2Score = 0
        });

        db.ClinicalAlerts.Add(new ClinicalAlert
        {
            Id = Guid.NewGuid(), EncounterId = _activeIcuEncounterId, PatientId = patientIcu.Id,
            AlertType = AlertType.News2Emergency, Severity = AlertSeverity.Critical,
            Details = "NEWS2 score 7", Status = AlertStatus.Open,
            TriggeredAt = DateTimeOffset.UtcNow
        });

        db.SofaScores.Add(new SofaScore
        {
            Id = Guid.NewGuid(), EncounterId = _activeIcuEncounterId, PatientId = patientIcu.Id,
            TotalScore = 8, RespiratoryScore = 2, CoagulationScore = 1, LiverScore = 1,
            CardiovascularScore = 2, CnsScore = 1, RenalScore = 1,
            DeltaFromBaseline = 2, CalculatedAt = DateTimeOffset.UtcNow,
            CreatedAt = DateTimeOffset.UtcNow
        });

        db.GcsScores.Add(new GcsScore
        {
            Id = Guid.NewGuid(), EncounterId = _activeIcuEncounterId, PatientId = patientIcu.Id,
            EyeScore = 3, VerbalScore = 4, MotorScore = 5, TotalScore = 12,
            Classification = "MODERATE", CalculatedAt = DateTimeOffset.UtcNow,
            CreatedAt = DateTimeOffset.UtcNow
        });

        db.Observations.Add(new Observation
        {
            Id = Guid.NewGuid(), EncounterId = _activeIcuEncounterId,
            ObservationCode = "HEART_RATE", Value = 110m, Unit = "bpm",
            Source = ObservationSource.Manual,
            RecordedAt = DateTimeOffset.UtcNow.AddHours(-3),
            CreatedAt = DateTimeOffset.UtcNow
        });

        await db.SaveChangesAsync();
    }

    public Task DisposeAsync() => Task.CompletedTask;

    [Fact]
    public async Task ListActiveEncounters_ReturnsSummariesWithPatientNames()
    {
        var resp = await _client.GetAsync("/api/v1/encounters?status=ACTIVE&page=1&pageSize=20");
        resp.StatusCode.Should().Be(HttpStatusCode.OK);

        var body = await resp.Content.ReadFromJsonAsync<JsonDocument>();
        var items = body!.RootElement.GetProperty("data").GetProperty("items");
        items.GetArrayLength().Should().Be(2);

        var icu = items.EnumerateArray()
            .First(i => i.GetProperty("encounterId").GetGuid() == _activeIcuEncounterId);

        icu.GetProperty("firstName").GetString().Should().Be("Alice");
        icu.GetProperty("lastName").GetString().Should().Be("Icu");
        icu.GetProperty("mrn").GetString().Should().Be("MRN-WARD-001");
        icu.GetProperty("roomBed").GetString().Should().Be("ICU-3");
        icu.GetProperty("news2Score").GetInt32().Should().Be(7);
        icu.GetProperty("openAlertCount").GetInt32().Should().Be(1);
        icu.GetProperty("qsofaScore").GetInt32().Should().Be(0);
        icu.GetProperty("sofaScore").GetInt32().Should().Be(8);
        icu.GetProperty("sofaDelta").GetInt32().Should().Be(2);
        icu.GetProperty("gcsScore").GetInt32().Should().Be(12);
        icu.GetProperty("gcsClassification").GetString().Should().Be("MODERATE");
        icu.GetProperty("attendingPhysician").GetString().Should().Be("Dr. Ward");
        icu.GetProperty("lastObservationAt").GetDateTimeOffset().Should().NotBe(default);
    }

    [Fact]
    public async Task ListByDepartment_FiltersCorrectly()
    {
        var resp = await _client.GetAsync("/api/v1/encounters?status=ACTIVE&department=SURGERY");
        resp.StatusCode.Should().Be(HttpStatusCode.OK);

        var body = await resp.Content.ReadFromJsonAsync<JsonDocument>();
        var items = body!.RootElement.GetProperty("data").GetProperty("items");
        items.GetArrayLength().Should().Be(1);
        items[0].GetProperty("encounterId").GetGuid().Should().Be(_activeSurgeryEncounterId);
        items[0].GetProperty("firstName").GetString().Should().Be("Bob");
    }

    [Fact]
    public async Task ListInvalidStatus_Returns400()
    {
        var resp = await _client.GetAsync("/api/v1/encounters?status=Active");
        resp.StatusCode.Should().Be(HttpStatusCode.BadRequest);
    }
}
