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

[Collection("Integration")]
public class PhiEncryptionTests
{
    private readonly ApiFixture _fixture;

    public PhiEncryptionTests(ApiFixture fixture) => _fixture = fixture;

    [Fact]
    public async Task PatientPhi_StoredEncrypted_ReturnsDecryptedViaApi()
    {
        var client = _fixture.CreateClient();
        client.ClearAuth();
        client.AsAdmin();

        var registerResp = await client.PostAsJsonAsync("/api/v1/patients", new
        {
            firstName = "Encrypted",
            lastName = "Patient",
            dateOfBirth = "1990-05-20",
            gender = "female"
        });
        registerResp.EnsureSuccessStatusCode();
        var body = await registerResp.Content.ReadFromJsonAsync<JsonElement>();
        var patientId = body.GetProperty("data").GetProperty("id").GetGuid();

        // Raw DB check — first_name should NOT equal plaintext
        using var scope = _fixture.Services.CreateScope();
        var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
        var raw = await db.Database
            .SqlQuery<string>($"SELECT first_name AS \"Value\" FROM patients WHERE id = {patientId}")
            .FirstAsync();
        raw.Should().NotBe("Encrypted");

        // API returns decrypted
        var getResp = await client.GetAsync($"/api/v1/patients/{patientId}");
        getResp.EnsureSuccessStatusCode();
        var patient = await getResp.Content.ReadFromJsonAsync<JsonElement>();
        patient.GetProperty("data").GetProperty("firstName").GetString()
            .Should().Be("Encrypted");
    }

    [Fact]
    public async Task PatientView_WritesPhiAccessLog()
    {
        var client = _fixture.CreateClient();
        client.ClearAuth();
        var nurseId = Guid.Parse("11111111-1111-1111-1111-111111111111");
        client.AsNurse(nurseId);

        await client.PostAsJsonAsync("/api/v1/patients", new
        {
            firstName = "PhiLog",
            lastName = "TestPatient",
            dateOfBirth = "1975-03-15",
            gender = "male"
        });

        var listResp = await client.GetAsync("/api/v1/patients?pageSize=1");
        listResp.EnsureSuccessStatusCode();
        var list = await listResp.Content.ReadFromJsonAsync<JsonElement>();
        var patientId = list.GetProperty("data").GetProperty("items")[0].GetProperty("id").GetGuid();

        await client.GetAsync($"/api/v1/patients/{patientId}");

        client.ClearAuth();
        client.AsAdmin();
        var logsResp = await client.GetAsync($"/api/v1/phi-access-logs?patientId={patientId}");
        logsResp.EnsureSuccessStatusCode();
        var logs = await logsResp.Content.ReadFromJsonAsync<JsonElement>();
        logs.GetProperty("data").GetProperty("totalCount").GetInt32()
            .Should().BeGreaterThan(0);
    }

    [Fact]
    public async Task NameSearch_FindsEncryptedPatient()
    {
        var client = _fixture.CreateClient();
        client.ClearAuth();
        client.AsAdmin();

        await client.PostAsJsonAsync("/api/v1/patients", new
        {
            firstName = "Searchable",
            lastName = "UniqueName",
            dateOfBirth = "1985-01-01",
            gender = "male"
        });

        var resp = await client.GetAsync("/api/v1/patients?q=Searchable+UniqueName");
        resp.EnsureSuccessStatusCode();
        var body = await resp.Content.ReadFromJsonAsync<JsonElement>();
        body.GetProperty("data").GetProperty("totalCount").GetInt32()
            .Should().BeGreaterThan(0);
    }
}