"""Tier 4: Real-World Clinical Workflows & End-to-End Scenarios.

Replicates complete oncology journeys in Hospitalisation à Domicile (HAD):
- Scenario 1: Acute Febrile Neutropenia Emergency Journey
- Scenario 2: Routine Home Nurse Clinical Observation & Summary Export
- Scenario 3: Multi-Patient Home Hospitalization Cycle (AC-T vs FOLFOX6)
- Scenario 4: Clinician Observation vs Patient Self-Report Differentiation
"""

import pytest


@pytest.mark.tier4
class TestClinicalWorkflows:
    """End-to-end clinical oncology journeys."""

    def test_scenario_febrile_neutropenia_emergency(
        self, patient_client, oncologist_client, nurse_client, session_server
    ):
        """Clinical Scenario 1: Acute Febrile Neutropenia Emergency.

        Context: Jeanne Durand (Patient 1, on AC-T protocol) experiences chills
        and fever (38.7°C) on Day 8 of Cycle 4.
        """
        # Step 1: Patient logs in and submits constitutional symptom report
        report_payload = {
            "patient_id": 1,
            "symptom_id": "febrile_neutropenia",
            "symptom_category": "constitutional",
            "severity_score": 3,
            "lab_values": {"anc_mm3": 800, "temp_celsius": 38.7},
            "notes": "Température 38.7°C mesurée à 14h, frissons intenses, neutropénie connue",
        }
        rep_resp = patient_client.post("/api/reports", json=report_payload)
        assert rep_resp.status_code == 201
        rep_data = rep_resp.json()
        report_id = rep_data["report_id"]
        grading = rep_data["grading"]
        alert = rep_data["alert"]

        # Step 2: Verify CTCAE Grade 3/4 and Emergency Alert
        assert grading["grade"] in (3, 4)
        assert alert is not None
        assert alert["alert_type"] == "emergency"
        assert alert["patient_id"] == 1

        # Step 3: Verify French patient emergency guidance is accessible
        guidance_resp = patient_client.get("/api/guidance?symptom_id=fever&grade=3")
        assert guidance_resp.status_code == 200
        guidance_data = guidance_resp.json()
        assert guidance_data["symptom_id"] == "fever"
        assert "guidance" in guidance_data

        # Step 4: Oncologist Dr. Martin reviews alerts and timeline
        onco_alerts_resp = oncologist_client.get("/api/alerts?patient_id=1")
        assert onco_alerts_resp.status_code == 200
        emergency_alerts = [
            a for a in onco_alerts_resp.json().get("alerts", [])
            if a["alert_type"] == "emergency" and a["report_id"] == report_id
        ]
        assert len(emergency_alerts) == 1
        emergency_alert_id = emergency_alerts[0]["id"]

        # Step 5: Oncologist acknowledges emergency alert
        ack_resp = oncologist_client.post(f"/api/alerts/{emergency_alert_id}/acknowledge")
        assert ack_resp.status_code == 200

        # Step 6: Oncologist dispatches urgent message to HAD nurse
        msg_payload = {
            "recipient_id": nurse_client.current_user["id"],
            "recipient_role": "had_nurse",
            "patient_id": 1,
            "subject": "URGENT - Suspicion neutropénie fébrile Jeanne Durand",
            "body": "Passage immédiat au domicile requis. Bilan sanguin en urgence (NFS + hémocultures) et antibiothérapie probabiliste selon protocole.",
            "message_type": "care_team",
        }
        msg_resp = oncologist_client.post("/api/messages", json=msg_payload)
        assert msg_resp.status_code == 201

        # Step 7: Nurse reads the instruction message
        inbox_resp = nurse_client.get("/api/messages?patient_id=1")
        assert inbox_resp.status_code == 200
        nurse_msgs = inbox_resp.json().get("messages", [])
        assert any("neutropénie fébrile" in m.get("subject", "") for m in nurse_msgs)

    def test_scenario_nurse_home_visit_and_clinical_export(
        self, nurse_client, oncologist_client
    ):
        """Clinical Scenario 2: Routine Home Nurse Visit and Export.

        Context: Nurse Moret conducts scheduled home visit, reviews symptom history,
        enters clinical observation, and exports summary.
        """
        # Step 1: Nurse reviews historical reports for patient 1
        reports_resp = nurse_client.get("/api/reports?patient_id=1")
        assert reports_resp.status_code == 200
        reports = reports_resp.json().get("reports", [])
        assert len(reports) >= 1

        # Step 2: Nurse enters observation report
        obs_payload = {
            "patient_id": 1,
            "symptom_id": "fatigue",
            "symptom_category": "constitutional",
            "severity_score": 1,
            "notes": "Visite HAD: TA 120/75, pouls 74 bpm, apyretique. Fatigue legere post-chimio bien toleree.",
        }
        obs_resp = nurse_client.post("/api/reports", json=obs_payload)
        assert obs_resp.status_code == 201
        obs_report_id = obs_resp.json()["report_id"]

        # Step 3: Timeline reflects the newly added clinical note
        tl_resp = nurse_client.get("/api/timeline?patient_id=1")
        assert tl_resp.status_code == 200
        events = tl_resp.json()["events"]
        assert any(e["event_type"] == "report" for e in events)

        # Step 4: Nurse generates structured clinical export summary
        export_resp = nurse_client.get("/api/export/summary?patient_id=1")
        assert export_resp.status_code == 200
        summary = export_resp.json()

        # Step 5: Validate clinical summary structure
        assert "patient" in summary
        assert summary["patient"]["mrn"] == "MRN-2024-001"
        assert "treatment_plans" in summary
        assert len(summary["treatment_plans"]) >= 1
        assert "toxicity_summary" in summary
        assert "fatigue" in summary["toxicity_summary"]
        assert "generated_at" in summary
        assert summary["generated_by"] == nurse_client.current_user["username"]

    def test_scenario_multi_patient_chemotherapy_cycles(
        self, api_client, session_server
    ):
        """Clinical Scenario 3: Multi-Patient Chemo Cycle Segregation.

        Simulates Patient 1 (Breast Cancer, AC-T) and Patient 2 (Colorectal, FOLFOX6)
        reporting symptoms on their respective cycles, verified by Dr. Martin.
        """
        from conftest import HADClient

        # Authenticate Patient 1 (Jeanne Durand)
        p1 = HADClient(session_server.base_url)
        p1.login("patient.durand", "demo123")

        # Authenticate Patient 2 (Pierre Moreau)
        p2 = HADClient(session_server.base_url)
        p2.login("patient.moreau", "demo123")

        # Patient 1 reports Grade 2 Nausea
        r1 = p1.post("/api/reports", json={
            "patient_id": 1,
            "symptom_id": "nausea",
            "symptom_category": "gastrointestinal",
            "severity_score": 5,
            "notes": "Patient 1 Cycle 4 AC-T nausea",
        })
        assert r1.status_code == 201
        assert r1.json()["grading"]["grade"] == 2
        assert r1.json()["alert"]["alert_type"] == "urgent"

        # Patient 2 reports Grade 1 Peripheral Neuropathy (common in FOLFOX/Oxaliplatin)
        r2 = p2.post("/api/reports", json={
            "patient_id": 2,
            "symptom_id": "peripheral_neuropathy",
            "symptom_category": "neurologic",
            "severity_score": 1,
            "notes": "Patient 2 FOLFOX cycle paresthesies distales",
        })
        assert r2.status_code == 201
        assert r2.json()["grading"]["grade"] == 1
        assert r2.json().get("alert") is None  # Grade 1 is routine

        # Oncologist Dr. Martin reviews both patient timelines
        onco = HADClient(session_server.base_url)
        onco.login("dr.martin", "demo123")

        tl1 = onco.get("/api/timeline?patient_id=1")
        assert tl1.status_code == 200
        tl1_events = [e["title"].lower() for e in tl1.json()["events"]]
        assert any("nausea" in t for t in tl1_events)

        tl2 = onco.get("/api/timeline?patient_id=2")
        assert tl2.status_code == 200
        tl2_events = [e["title"].lower() for e in tl2.json()["events"]]
        assert any("neuropathy" in t for t in tl2_events)

    def test_scenario_clinician_observation_vs_patient_self_report(
        self, patient_client, nurse_client, session_server
    ):
        """Clinical Scenario 4: Clinician Observation vs Patient Self-Report."""
        # Patient submits subjective self-report
        p_resp = patient_client.post("/api/reports", json={
            "patient_id": 1,
            "symptom_id": "nausea",
            "symptom_category": "gastrointestinal",
            "severity_score": 2,
            "notes": "Auto-evaluation patient: nausees presentes apres le petit dejeuner",
        })
        assert p_resp.status_code == 201
        p_rep_id = p_resp.json()["report_id"]

        # Nurse submits clinician observation
        n_resp = nurse_client.post("/api/reports", json={
            "patient_id": 1,
            "symptom_id": "nausea",
            "symptom_category": "gastrointestinal",
            "severity_score": 1,
            "notes": "Evaluation IDE a domicile: bon etat general, prise efficace du primperan",
        })
        assert n_resp.status_code == 201
        n_rep_id = n_resp.json()["report_id"]

        # Verify distinct reporter IDs in SQLite
        p_row = session_server.query_db("SELECT reporter_id FROM toxicity_reports WHERE id = ?", (p_rep_id,))
        n_row = session_server.query_db("SELECT reporter_id FROM toxicity_reports WHERE id = ?", (n_rep_id,))

        assert p_row[0]["reporter_id"] == patient_client.current_user["id"]
        assert n_row[0]["reporter_id"] == nurse_client.current_user["id"]
        assert p_row[0]["reporter_id"] != n_row[0]["reporter_id"]
