"""Phase 13.6 — Pharmacy Network tests."""
from __future__ import annotations

import pytest

from app.events.publisher import get_event_publisher
from app.events.types import HealthcareEventType
from app.providers.mocks import MockCommunicationProvider
from app.tests.conftest import TENANT_A, tenant_headers
from app.validators.pharmacy import ensure_prescription_transition
from app.models.types import PrescriptionLifecycleAction, PrescriptionOrderStatus
from shared.exceptions import AppError


async def _seed_pharmacy(client):
    headers = tenant_headers(TENANT_A)
    clinic = await client.post(
        "/api/v1/clinics",
        headers=headers,
        json={"code": "CLN136", "name": "Rx Clinic", "status": "active"},
    )
    clinic_id = clinic.json()["id"]
    doctor = await client.post(
        "/api/v1/doctors",
        headers=headers,
        json={"user_id": "doc-136", "clinic_id": clinic_id, "code": "DOC136", "display_name": "Dr Rx"},
    )
    doctor_id = doctor.json()["id"]
    patient = await client.post(
        "/api/v1/patients",
        headers=headers,
        json={
            "user_id": "pat-136",
            "code": "PAT136",
            "display_name": "Rx Patient",
            "contact": {"phone": "+989129999999"},
        },
    )
    patient_id = patient.json()["id"]
    pharmacy = await client.post(
        "/api/v1/pharmacies",
        headers=headers,
        json={"code": "PH1", "name": "City Pharmacy"},
    )
    assert pharmacy.status_code == 201
    return doctor_id, patient_id, pharmacy.json()["id"]


def test_prescription_lifecycle_validator():
    ensure_prescription_transition(
        action=PrescriptionLifecycleAction.ACCEPT, current=PrescriptionOrderStatus.SUBMITTED
    )
    with pytest.raises(AppError):
        ensure_prescription_transition(
            action=PrescriptionLifecycleAction.ACCEPT, current=PrescriptionOrderStatus.READY
        )


@pytest.mark.asyncio
async def test_prescription_fulfillment_lifecycle(client):
    MockCommunicationProvider.reset()
    doctor_id, patient_id, pharmacy_id = await _seed_pharmacy(client)
    headers = tenant_headers(TENANT_A)

    order = await client.post(
        "/api/v1/prescription-orders",
        headers=headers,
        json={
            "pharmacy_id": pharmacy_id,
            "patient_id": patient_id,
            "doctor_id": doctor_id,
            "code": "RX1",
            "lines": [
                {"line_no": 1, "medication_code": "MED001", "display": "Amoxicillin", "quantity": 1}
            ],
        },
    )
    assert order.status_code == 201, order.text
    oid = order.json()["id"]
    version = order.json()["version"]

    for action in ("accept", "prepare", "mark-ready"):
        resp = await client.post(
            f"/api/v1/prescription-orders/{oid}/{action}",
            headers=headers,
            json={"version": version},
        )
        assert resp.status_code == 200, resp.text
        version = resp.json()["version"]
        assert resp.json()["status"] in ("accepted", "preparing", "ready")

    assert len(MockCommunicationProvider.sent) == 1

    picked = await client.post(
        f"/api/v1/prescription-orders/{oid}/complete-pickup",
        headers=headers,
        json={"version": version},
    )
    assert picked.status_code == 200
    assert picked.json()["status"] == "picked_up"

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


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