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

/// <summary>
/// Drives lab-result batches with potassium observations through the HTTP pipeline.
/// Uses DataSeeder usernames (intake1, entry1, verifier1, approver1).
/// </summary>
public static class CorrectionPipelineHelper
{
    /// <summary>
    /// Creates a LAB_RESULTS batch with K and Na draft observations, drives it through
    /// verify → approve, and returns the promoted batch ID and live patient ID.
    /// </summary>
    public static async Task<(Guid BatchId, Guid PatientId)> PromoteLabBatchAsync(
        ApiFixture fixture,
        decimal potassiumValue,
        decimal sodiumValue = 140m)
    {
        var batchId = await CreateLabBatchThroughVerificationAsync(fixture, potassiumValue, sodiumValue);

        var client = await AuthHelper.LoginAsync(fixture, "approver1");
        client.DefaultRequestHeaders.Add("Idempotency-Key", Guid.NewGuid().ToString());

        var approveResponse = await client.PostAsJsonAsync(
            $"/api/v1/digitization-batches/{batchId}/approve",
            new { enableRetroactiveAlerts = false });
        approveResponse.EnsureSuccessStatusCode();

        using var scope = fixture.Services.CreateScope();
        var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
        var batch = await db.DigitizationBatches.AsNoTracking().FirstAsync(b => b.Id == batchId);

        return (batchId, batch.PatientId!.Value);
    }

    /// <summary>
    /// Uploads a correction batch linked to a promoted batch, drives entry → verify → approve.
    /// </summary>
    public static async Task<Guid> PromoteCorrectionBatchAsync(
        ApiFixture fixture,
        Guid supersedesBatchId,
        Guid patientId,
        decimal potassiumValue,
        decimal sodiumValue = 140m)
    {
        var client = await AuthHelper.LoginAsync(fixture, "intake1");

        var fileContent = new ByteArrayContent(System.Text.Encoding.UTF8.GetBytes("%PDF-correction"));
        fileContent.Headers.ContentType =
            new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");

        var formData = new MultipartFormDataContent
        {
            { fileContent, "file", $"correction-{Guid.NewGuid()}.pdf" },
            { new StringContent("LAB_RESULTS"), "batchType" },
            { new StringContent("BACKFILL"), "track" },
            { new StringContent(patientId.ToString()), "patientId" },
            { new StringContent(supersedesBatchId.ToString()), "supersedesBatchId" }
        };

        var uploadResponse = await client.PostAsync("/api/v1/digitization-batches", formData);
        uploadResponse.EnsureSuccessStatusCode();

        var uploadBody = await uploadResponse.Content.ReadFromJsonAsync<JsonElement>();
        var correctionBatchId = uploadBody.GetProperty("data").GetProperty("id").GetGuid();

        // Data entry — correction re-enters all observations
        client = await AuthHelper.LoginAsync(fixture, "entry2");
        await client.PostAsJsonAsync(
            $"/api/v1/digitization-batches/{correctionBatchId}/draft/observations",
            new { observationCode = "K", value = potassiumValue, unit = "mmol/L",
                  recordedAt = DateTimeOffset.UtcNow });
        await client.PostAsJsonAsync(
            $"/api/v1/digitization-batches/{correctionBatchId}/draft/observations",
            new { observationCode = "Na", value = sodiumValue, unit = "mmol/L",
                  recordedAt = DateTimeOffset.UtcNow });
        var submitResponse = await client.PostAsync(
            $"/api/v1/digitization-batches/{correctionBatchId}/submit-for-verification", null);
        submitResponse.EnsureSuccessStatusCode();

        // Verify and approve
        client = await AuthHelper.LoginAsync(fixture, "verifier2");
        var verifyResponse = await client.PostAsJsonAsync(
            $"/api/v1/digitization-batches/{correctionBatchId}/verify",
            new { fieldChecks = new[] { new { fieldName = "observation.K", status = "ok", note = (string?)null } }, passed = true });
        verifyResponse.EnsureSuccessStatusCode();

        client = await AuthHelper.LoginAsync(fixture, "approver2");
        client.DefaultRequestHeaders.Add("Idempotency-Key", Guid.NewGuid().ToString());
        var approveResponse = await client.PostAsJsonAsync(
            $"/api/v1/digitization-batches/{correctionBatchId}/approve",
            new { enableRetroactiveAlerts = false });
        approveResponse.EnsureSuccessStatusCode();

        return correctionBatchId;
    }

    private static async Task<Guid> CreateLabBatchThroughVerificationAsync(
        ApiFixture fixture, decimal potassiumValue, decimal sodiumValue)
    {
        var client = await AuthHelper.LoginAsync(fixture, "intake1");

        var fileContent = new ByteArrayContent(System.Text.Encoding.UTF8.GetBytes("%PDF-lab"));
        fileContent.Headers.ContentType =
            new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");

        var formData = new MultipartFormDataContent
        {
            { fileContent, "file", $"lab-{Guid.NewGuid()}.pdf" },
            { new StringContent("LAB_RESULTS"), "batchType" },
            { new StringContent("BACKFILL"), "track" }
        };

        var uploadResponse = await client.PostAsync("/api/v1/digitization-batches", formData);
        uploadResponse.EnsureSuccessStatusCode();

        var uploadBody = await uploadResponse.Content.ReadFromJsonAsync<JsonElement>();
        var batchId = uploadBody.GetProperty("data").GetProperty("id").GetGuid();

        client = await AuthHelper.LoginAsync(fixture, "entry1");
        await client.PutAsJsonAsync(
            $"/api/v1/digitization-batches/{batchId}/draft/patient",
            new { fullName = "Correction Test Patient", dateOfBirth = "1980-01-15", sex = "Female" });
        await client.PutAsJsonAsync(
            $"/api/v1/digitization-batches/{batchId}/draft/encounter",
            new { admissionDate = "2024-06-01T08:00:00Z", department = Department.InternalMedicine.ToDbString(),
                  roomBed = "4A-12", admissionReason = "Electrolyte panel", status = "active" });
        await client.PostAsJsonAsync(
            $"/api/v1/digitization-batches/{batchId}/draft/observations",
            new { observationCode = "K", value = potassiumValue, unit = "mmol/L",
                  recordedAt = DateTimeOffset.UtcNow });
        await client.PostAsJsonAsync(
            $"/api/v1/digitization-batches/{batchId}/draft/observations",
            new { observationCode = "Na", value = sodiumValue, unit = "mmol/L",
                  recordedAt = DateTimeOffset.UtcNow });
        await client.PostAsync(
            $"/api/v1/digitization-batches/{batchId}/submit-for-verification", null);

        client = await AuthHelper.LoginAsync(fixture, "verifier1");
        await client.PostAsJsonAsync(
            $"/api/v1/digitization-batches/{batchId}/verify",
            new { fieldChecks = new[] { new { fieldName = "observation.K", status = "ok", note = (string?)null } }, passed = true });

        return batchId;
    }
}