"""Phase 13.5 — Medical Record tests."""
from __future__ import annotations

import pytest

from app.events.types import HealthcareEventType
from app.events.publisher import get_event_publisher
from app.tests.conftest import TENANT_A, tenant_headers
from app.models.types import EncounterStatus
from app.validators.medical_records import ensure_encounter_mutable
from shared.exceptions import AppError


async def _seed_record(client):
    headers = tenant_headers(TENANT_A)
    clinic = await client.post(
        "/api/v1/clinics",
        headers=headers,
        json={"code": "CLN135", "name": "Record Clinic", "status": "active"},
    )
    clinic_id = clinic.json()["id"]
    doctor = await client.post(
        "/api/v1/doctors",
        headers=headers,
        json={"user_id": "doc-135", "clinic_id": clinic_id, "code": "DOC135", "display_name": "Dr Record"},
    )
    doctor_id = doctor.json()["id"]
    patient = await client.post(
        "/api/v1/patients",
        headers=headers,
        json={"user_id": "pat-135", "code": "PAT135", "display_name": "Record Patient"},
    )
    patient_id = patient.json()["id"]
    record = await client.post(
        "/api/v1/medical-records",
        headers=headers,
        json={"clinic_id": clinic_id, "patient_id": patient_id, "code": "MR1"},
    )
    assert record.status_code == 201
    return doctor_id, record.json()["id"]


def test_encounter_immutability_validator():
    with pytest.raises(AppError) as exc:
        ensure_encounter_mutable(EncounterStatus.FINALIZED)
    assert exc.value.error_code == "encounter_finalized"


@pytest.mark.asyncio
async def test_encounter_finalize_immutability(client):
    doctor_id, record_id = await _seed_record(client)
    headers = tenant_headers(TENANT_A)

    enc = await client.post(
        "/api/v1/encounters",
        headers=headers,
        json={
            "medical_record_id": record_id,
            "doctor_id": doctor_id,
            "code": "ENC1",
            "chief_complaint": "Headache",
        },
    )
    assert enc.status_code == 201
    eid = enc.json()["id"]
    version = enc.json()["version"]

    updated = await client.patch(
        f"/api/v1/encounters/{eid}",
        headers=headers,
        json={"clinical_summary": "Migraine suspected", "version": version},
    )
    assert updated.status_code == 200
    version = updated.json()["version"]

    finalized = await client.post(
        f"/api/v1/encounters/{eid}/finalize",
        headers=headers,
        json={"version": version},
    )
    assert finalized.status_code == 200
    assert finalized.json()["status"] == "finalized"

    blocked = await client.patch(
        f"/api/v1/encounters/{eid}",
        headers=headers,
        json={"clinical_summary": "Changed", "version": finalized.json()["version"]},
    )
    assert blocked.status_code == 409

    events = {e.event_type for e in get_event_publisher().published}
    assert HealthcareEventType.ENCOUNTER_FINALIZED.value in events


@pytest.mark.asyncio
async def test_clinical_lists_and_access(client):
    _, record_id = await _seed_record(client)
    headers = tenant_headers(TENANT_A)

    await client.post(
        f"/api/v1/medical-records/{record_id}/conditions",
        headers=headers,
        json={"code": "COND1", "display": "Hypertension"},
    )
    await client.post(
        f"/api/v1/medical-records/{record_id}/allergies",
        headers=headers,
        json={"code": "ALG1", "substance": "Penicillin"},
    )

    record = await client.get(f"/api/v1/medical-records/{record_id}", headers=headers)
    assert record.status_code == 200

    lists = await client.get(
        f"/api/v1/medical-records/{record_id}/clinical-lists", headers=headers
    )
    assert lists.status_code == 200
    assert len(lists.json()["conditions"]) >= 1


@pytest.mark.asyncio
async def test_phase_135_capabilities(client):
    caps = await client.get("/capabilities")
    assert caps.json()["features"]["medical_records"] is True
