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

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

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

    public async Task InitializeAsync() => await ResetAndSeedAsync();

    public Task DisposeAsync() => Task.CompletedTask;

    private async Task ResetAndSeedAsync()
    {
        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-ORD-001", FirstName = "Order", LastName = "Test",
            DateOfBirth = new DateOnly(1988, 2, 10), Gender = "F", CreatedAt = DateTimeOffset.UtcNow
        };
        var encounter = new Encounter
        {
            Id = Guid.NewGuid(), PatientId = patient.Id, EncounterType = EncounterType.Inpatient,
            Status = EncounterStatus.Active, Department = Department.GeneralMedicine,
            AttendingPhysician = "Dr. Order", AdmittedAt = DateTimeOffset.UtcNow,
            CreatedAt = DateTimeOffset.UtcNow
        };
        db.Patients.Add(patient);
        db.Encounters.Add(encounter);
        await db.SaveChangesAsync();

        _encounterId = encounter.Id;
    }

    [Fact]
    public async Task CreateOrder_Returns201()
    {
        await ResetAndSeedAsync();

        var resp = await _client.PostAsJsonAsync(
            $"/api/v1/encounters/{_encounterId}/orders",
            new CreateOrderRequest(OrderType.Lab, "CBC with differential", "Dr. Test"));

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

    [Fact]
    public async Task ListOrders_ReturnsPaginated()
    {
        await ResetAndSeedAsync();

        await _client.PostAsJsonAsync(
            $"/api/v1/encounters/{_encounterId}/orders",
            new CreateOrderRequest(OrderType.Lab, "BMP", "Dr. A"));
        await _client.PostAsJsonAsync(
            $"/api/v1/encounters/{_encounterId}/orders",
            new CreateOrderRequest(OrderType.Imaging, "Chest X-ray", "Dr. B"));

        var resp = await _client.GetAsync($"/api/v1/encounters/{_encounterId}/orders");
        resp.StatusCode.Should().Be(HttpStatusCode.OK);
        var body = await resp.Content.ReadFromJsonAsync<JsonDocument>();
        body!.RootElement.GetProperty("data").GetProperty("totalCount").GetInt32()
            .Should().Be(2);
    }

    [Fact]
    public async Task RecordResult_TransitionsToResulted()
    {
        await ResetAndSeedAsync();

        var createResp = await _client.PostAsJsonAsync(
            $"/api/v1/encounters/{_encounterId}/orders",
            new CreateOrderRequest(OrderType.Lab, "Potassium", "Dr. Test"));
        var createBody = await createResp.Content.ReadFromJsonAsync<JsonDocument>();
        var orderId = createBody!.RootElement.GetProperty("data").GetProperty("id").GetGuid();

        var resultResp = await _client.PatchAsJsonAsync(
            $"/api/v1/orders/{orderId}/result",
            new RecordOrderResultRequest("Potassium 4.2 mEq/L — within normal limits"));

        resultResp.StatusCode.Should().Be(HttpStatusCode.OK);
        var body = await resultResp.Content.ReadFromJsonAsync<JsonDocument>();
        body!.RootElement.GetProperty("data").GetProperty("status").GetString()
            .Should().Be("Resulted");
        body.RootElement.GetProperty("data").GetProperty("resultSummary").GetString()
            .Should().Contain("4.2");
    }

    [Fact]
    public async Task CancelResultedOrder_Returns409()
    {
        await ResetAndSeedAsync();

        var createResp = await _client.PostAsJsonAsync(
            $"/api/v1/encounters/{_encounterId}/orders",
            new CreateOrderRequest(OrderType.Lab, "Glucose", "Dr. Test"));
        var orderId = (await createResp.Content.ReadFromJsonAsync<JsonDocument>())!
            .RootElement.GetProperty("data").GetProperty("id").GetGuid();

        await _client.PatchAsJsonAsync(
            $"/api/v1/orders/{orderId}/result",
            new RecordOrderResultRequest("Normal"));

        var resp = await _client.PatchAsJsonAsync(
            $"/api/v1/orders/{orderId}/status",
            new TransitionOrderStatusRequest(OrderStatus.Cancelled));

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