"""
Unit and integration tests for Clinical Result Entry and Demographic Range Engine.
"""

from datetime import UTC, date, datetime
from decimal import Decimal
from uuid import uuid4

import pytest
import pytest_asyncio
from httpx import AsyncClient
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.security import create_access_token, hash_password
from app.models.audit import AuditCategory, AuditLog
from app.models.lab import Lab
from app.models.order import OrderStatus, OrderTest, OrderTestStatus, VisitOrder
from app.models.patient import Gender, Patient
from app.models.report import Report, ReportStatus
from app.models.test import (
    Test as LabTest,
)
from app.models.test import (
    TestCategory as LabCategory,
)
from app.models.test import (
    TestParameter as LabParameter,
)
from app.models.test import (
    TestParameterRange as LabParameterRange,
)
from app.models.test import (
    TestResultType as LabResultType,
)
from app.models.user import User, UserRole
from app.repositories.permission_repository import PermissionRepository
from app.services.clinical_engine import ClinicalEngine

# ─────────────────────────────────────────────────────────────────────────────
# UNIT TESTS: ClinicalEngine
# ─────────────────────────────────────────────────────────────────────────────


def test_calculate_patient_age() -> None:
    """Test age calculation from DOB and fallback."""
    today = datetime.now(UTC).date()

    # Exact 25 years ago
    dob_25 = date(today.year - 25, today.month, today.day)
    assert ClinicalEngine.calculate_patient_age(dob_25) == 25

    # Birthday hasn't happened yet this year (subtract 1)
    if today.month < 12 or today.day < 28:
        dob_future_month = date(today.year - 20, 12, 28)
        assert ClinicalEngine.calculate_patient_age(dob_future_month) == 19

    # Fallback age when DOB is None
    assert ClinicalEngine.calculate_patient_age(None, fallback_age=42) == 42
    assert ClinicalEngine.calculate_patient_age(None, fallback_age=None) is None


def test_select_reference_range() -> None:
    """Test range selection based on patient sex and age."""
    param_id = uuid4()

    # Unisex general range
    r_unisex = LabParameterRange(
        parameter_id=param_id,
        gender=None,
        age_min=None,
        age_max=None,
        numeric_low=Decimal("10"),
        numeric_high=Decimal("20"),
    )
    # Male adult range
    r_male_adult = LabParameterRange(
        parameter_id=param_id,
        gender=Gender.MALE,
        age_min=18,
        age_max=65,
        numeric_low=Decimal("13.5"),
        numeric_high=Decimal("17.5"),
    )
    # Female adult range
    r_female_adult = LabParameterRange(
        parameter_id=param_id,
        gender=Gender.FEMALE,
        age_min=18,
        age_max=65,
        numeric_low=Decimal("12.0"),
        numeric_high=Decimal("15.5"),
    )
    # Pediatric range (unisex)
    r_pediatric = LabParameterRange(
        parameter_id=param_id,
        gender=None,
        age_min=0,
        age_max=12,
        numeric_low=Decimal("11.0"),
        numeric_high=Decimal("14.0"),
    )

    ranges = [r_unisex, r_male_adult, r_female_adult, r_pediatric]

    # Adult male (30yo) should match r_male_adult
    selected = ClinicalEngine.select_reference_range(ranges, Gender.MALE, 30)
    assert selected == r_male_adult

    # Adult female (28yo) should match r_female_adult
    selected = ClinicalEngine.select_reference_range(ranges, Gender.FEMALE, 28)
    assert selected == r_female_adult

    # Child (5yo) should match r_pediatric
    selected = ClinicalEngine.select_reference_range(ranges, Gender.MALE, 5)
    assert selected == r_pediatric

    # Elderly male (70yo) falls back to r_unisex
    selected = ClinicalEngine.select_reference_range(ranges, Gender.MALE, 70)
    assert selected == r_unisex


def test_evaluate_numeric_values() -> None:
    """Test numeric evaluation for normal, low, and high flags."""
    param = LabParameter(name="Hemoglobin")
    ref_range = LabParameterRange(
        numeric_low=Decimal("12.0"),
        numeric_high=Decimal("16.0"),
    )

    # Normal value
    flag, abnormal = ClinicalEngine.evaluate_value("14.2", param, ref_range)
    assert flag == "N"
    assert abnormal is False

    # Low value
    flag, abnormal = ClinicalEngine.evaluate_value("10.5", param, ref_range)
    assert flag == "L"
    assert abnormal is True

    # High value
    flag, abnormal = ClinicalEngine.evaluate_value("18.0", param, ref_range)
    assert flag == "H"
    assert abnormal is True


def test_evaluate_thousands_separators() -> None:
    """Thousand-group commas must never truncate a reading ('10,000' is 10000, not 10)."""
    from app.services.clinical_engine import normalize_numeric_input

    assert normalize_numeric_input("10,000") == "10000"
    assert normalize_numeric_input(" 3,800 ") == "3800"
    assert normalize_numeric_input("13.5") == "13.5"

    param = LabParameter(name="WBC")
    ref_range = LabParameterRange(
        numeric_low=Decimal("4000"),
        numeric_high=Decimal("11000"),
    )
    flag, abnormal = ClinicalEngine.evaluate_value("10,000", param, ref_range)
    assert flag == "N"
    assert abnormal is False

    flag, abnormal = ClinicalEngine.evaluate_value("3,000", param, ref_range)
    assert flag == "L"
    assert abnormal is True


def test_evaluate_calc_factor_and_text() -> None:
    """Test evaluation with calculation factor multiplier and text results."""
    # Calc factor: reading * 0.1
    param_calc = LabParameter(name="Scaled Param", calc_factor=Decimal("0.1"))
    ref_range = LabParameterRange(
        numeric_low=Decimal("1.0"),
        numeric_high=Decimal("2.0"),
    )
    # Raw 15 * 0.1 = 1.5 -> Normal
    flag, abnormal = ClinicalEngine.evaluate_value("15", param_calc, ref_range)
    assert flag == "N"
    assert abnormal is False

    # Raw 25 * 0.1 = 2.5 -> High
    flag, abnormal = ClinicalEngine.evaluate_value("25", param_calc, ref_range)
    assert flag == "H"
    assert abnormal is True

    # Text evaluation
    param_text = LabParameter(name="Blood Parasite")
    text_range = LabParameterRange(text_normal="Not Detected")

    flag, abnormal = ClinicalEngine.evaluate_value("not detected", param_text, text_range)
    assert flag == "N"
    assert abnormal is False

    flag, abnormal = ClinicalEngine.evaluate_value("Plasmodium vivax seen", param_text, text_range)
    assert flag == "ABNORMAL"
    assert abnormal is True


# ─────────────────────────────────────────────────────────────────────────────
# INTEGRATION FIXTURES & TESTS
# ─────────────────────────────────────────────────────────────────────────────


@pytest_asyncio.fixture(autouse=True)
async def seed_perms(db_session: AsyncSession) -> None:
    """Seed permissions for RBAC checks."""
    repo = PermissionRepository()
    await repo.seed_permissions(db_session)


@pytest_asyncio.fixture
async def sample_lab(db_session: AsyncSession) -> Lab:
    """Create test laboratory."""
    lab = Lab(name="Diagnostic Central Lab", address="Kathmandu")
    db_session.add(lab)
    await db_session.commit()
    await db_session.refresh(lab)
    return lab


@pytest_asyncio.fixture
async def other_lab(db_session: AsyncSession) -> Lab:
    """Create a separate branch laboratory."""
    lab = Lab(name="Remote Branch Lab", address="Biratnagar")
    db_session.add(lab)
    await db_session.commit()
    await db_session.refresh(lab)
    return lab


@pytest_asyncio.fixture
async def technician_token(db_session: AsyncSession, sample_lab: Lab) -> tuple[User, str]:
    """Create pathologist user and bearer token."""
    user = User(
        lab_id=sample_lab.id,
        name="Dr. Pathologist Anil",
        phone="9811223344",
        email="anil@munal.com",
        role=UserRole.PATHOLOGIST,
        hashed_password=hash_password("Pass123!"),
        is_active=True,
    )
    db_session.add(user)
    await db_session.commit()
    await db_session.refresh(user)
    token = create_access_token(
        subject=str(user.id),
        extra_claims={"email": user.email, "role": user.role.value, "lab_id": str(user.lab_id)},
    )
    return user, token


@pytest_asyncio.fixture
async def other_branch_token(db_session: AsyncSession, other_lab: Lab) -> tuple[User, str]:
    """Create pathologist user in other branch."""
    user = User(
        lab_id=other_lab.id,
        name="Dr. Other Branch",
        phone="9822334455",
        email="other@munal.com",
        role=UserRole.PATHOLOGIST,
        hashed_password=hash_password("Pass123!"),
        is_active=True,
    )
    db_session.add(user)
    await db_session.commit()
    await db_session.refresh(user)
    token = create_access_token(
        subject=str(user.id),
        extra_claims={"email": user.email, "role": user.role.value, "lab_id": str(user.lab_id)},
    )
    return user, token


@pytest_asyncio.fixture
async def clinical_setup(
    db_session: AsyncSession,
    sample_lab: Lab,
) -> tuple[VisitOrder, LabParameter, LabParameter]:
    """
    Setup patient, diagnostic test with parameters & reference ranges,
    and a visit order.
    """
    # 1. Patient: 30-year-old Male
    patient = Patient(
        lab_id=sample_lab.id,
        patient_code="P26-00088",
        name="Ramesh Thapa",
        gender=Gender.MALE,
        date_of_birth=date(1996, 5, 10),
        phone="9851000000",
    )
    db_session.add(patient)

    # 2. Test Category
    cat = LabCategory(lab_id=sample_lab.id, name="Hematology", description="Routine blood tests")
    db_session.add(cat)
    await db_session.flush()

    # 3. Test
    test = LabTest(
        lab_id=sample_lab.id,
        category_id=cat.id,
        name="Complete Blood Count",
        code="CBC",
        result_type=LabResultType.COMPOSITE,
        price=Decimal("450.00"),
    )
    db_session.add(test)
    await db_session.flush()

    # 4. Parameters
    p_hgb = LabParameter(
        test_id=test.id,
        name="Hemoglobin",
        unit="g/dL",
        decimal_places=1,
        sort_order=1,
    )
    p_wbc = LabParameter(
        test_id=test.id,
        name="White Blood Cells",
        unit="/cumm",
        decimal_places=0,
        sort_order=2,
    )
    db_session.add_all([p_hgb, p_wbc])
    await db_session.flush()

    # 5. Reference Ranges for HGB
    r_hgb_male = LabParameterRange(
        parameter_id=p_hgb.id,
        gender=Gender.MALE,
        age_min=18,
        age_max=65,
        numeric_low=Decimal("13.0"),
        numeric_high=Decimal("17.0"),
    )
    r_hgb_female = LabParameterRange(
        parameter_id=p_hgb.id,
        gender=Gender.FEMALE,
        age_min=18,
        age_max=65,
        numeric_low=Decimal("12.0"),
        numeric_high=Decimal("15.0"),
    )
    # Unisex range for WBC
    r_wbc_unisex = LabParameterRange(
        parameter_id=p_wbc.id,
        gender=None,
        age_min=None,
        age_max=None,
        numeric_low=Decimal("4000"),
        numeric_high=Decimal("11000"),
    )
    db_session.add_all([r_hgb_male, r_hgb_female, r_wbc_unisex])

    # 6. Order & OrderTest
    order = VisitOrder(
        lab_id=sample_lab.id,
        patient_id=patient.id,
        order_number="ORD/26/000888",
        status=OrderStatus.SAMPLE_COLLECTED,
    )
    db_session.add(order)
    await db_session.flush()

    order_test = OrderTest(
        order_id=order.id,
        test_id=test.id,
        price_at_order=test.price,
        status=OrderTestStatus.DRAFT,
    )
    db_session.add(order_test)
    await db_session.commit()
    await db_session.refresh(order)
    await db_session.refresh(p_hgb)
    await db_session.refresh(p_wbc)

    return order, p_hgb, p_wbc


@pytest.mark.asyncio
async def test_get_worksheet_success(
    client: AsyncClient,
    technician_token: tuple[User, str],
    clinical_setup: tuple[VisitOrder, LabParameter, LabParameter],
) -> None:
    """Test fetching tailored worksheet for an order."""
    _, token = technician_token
    order, p_hgb, p_wbc = clinical_setup

    res = await client.get(
        f"/api/v1/orders/{order.id}/results/worksheet",
        headers={"Authorization": f"Bearer {token}"},
    )
    assert res.status_code == 200
    data = res.json()["data"]

    assert data["order_id"] == str(order.id)
    assert data["patient_gender"] == "male"
    assert len(data["tests"]) == 1

    test_item = data["tests"][0]
    assert test_item["test_code"] == "CBC"
    assert len(test_item["parameters"]) == 2

    # Hemoglobin parameter: should match Male reference range (13.0 - 17.0)
    hgb_param = next(p for p in test_item["parameters"] if p["parameter_id"] == str(p_hgb.id))
    assert float(hgb_param["reference_low"]) == 13.0
    assert float(hgb_param["reference_high"]) == 17.0

    # WBC parameter: should match unisex range (4000 - 11000)
    wbc_param = next(p for p in test_item["parameters"] if p["parameter_id"] == str(p_wbc.id))
    assert float(wbc_param["reference_low"]) == 4000.0
    assert float(wbc_param["reference_high"]) == 11000.0


@pytest.mark.asyncio
async def test_get_worksheet_cross_branch_denied(
    client: AsyncClient,
    other_branch_token: tuple[User, str],
    clinical_setup: tuple[VisitOrder, LabParameter, LabParameter],
) -> None:
    """Test user from another branch cannot view worksheet."""
    _, token = other_branch_token
    order, _, _ = clinical_setup

    res = await client.get(
        f"/api/v1/orders/{order.id}/results/worksheet",
        headers={"Authorization": f"Bearer {token}"},
    )
    assert res.status_code == 404


@pytest.mark.asyncio
async def test_enter_results_evaluation_and_report_creation(
    client: AsyncClient,
    technician_token: tuple[User, str],
    clinical_setup: tuple[VisitOrder, LabParameter, LabParameter],
    db_session: AsyncSession,
) -> None:
    """
    Test entering results:
      - HGB = 11.5 (Low -> L, abnormal)
      - WBC = 7500 (Normal -> N, normal)
    Verifies auto-flagging, report creation, and status progression.
    """
    technician, token = technician_token
    order, p_hgb, p_wbc = clinical_setup

    payload = {
        "results": [
            {"parameter_id": str(p_hgb.id), "value": "11.5", "notes": "Slight anemia"},
            {"parameter_id": str(p_wbc.id), "value": "7500"},
        ],
        "notes": "Specimen clear, no hemolysis",
    }

    res = await client.post(
        f"/api/v1/orders/{order.id}/results",
        json=payload,
        headers={"Authorization": f"Bearer {token}"},
    )
    assert res.status_code == 200
    data = res.json()["data"]

    assert data["order_id"] == str(order.id)
    assert data["total_parameters_entered"] == 2
    assert data["abnormal_count"] == 1
    assert data["report_status"] == "draft"

    eval_results = data["evaluated_results"]
    hgb_eval = next(r for r in eval_results if r["parameter_id"] == str(p_hgb.id))
    assert hgb_eval["flag"] == "L"
    assert hgb_eval["is_abnormal"] is True

    wbc_eval = next(r for r in eval_results if r["parameter_id"] == str(p_wbc.id))
    assert wbc_eval["flag"] == "N"
    assert wbc_eval["is_abnormal"] is False

    # Check database persistence
    await db_session.refresh(order)
    assert order.status == OrderStatus.PROCESSING
    for ot in order.order_tests:
        assert ot.status == OrderTestStatus.PROCESSING

    audit_log = (
        await db_session.execute(
            select(AuditLog).where(
                AuditLog.action == "RESULTS_ENTERED", AuditLog.target_id == data["report_id"]
            )
        )
    ).scalar_one()
    assert audit_log.category == AuditCategory.CLINICAL.value
    assert audit_log.actor_id == technician.id
    assert audit_log.details == {
        "order_id": str(order.id),
        "version": 1,
        "status": "draft",
        "analyte_count": 2,
        "abnormal_count": 1,
    }
    assert "Slight anemia" not in str(audit_log.details)
    assert "Specimen clear" not in str(audit_log.details)


@pytest.mark.asyncio
async def test_enter_results_incremental_update(
    client: AsyncClient,
    technician_token: tuple[User, str],
    clinical_setup: tuple[VisitOrder, LabParameter, LabParameter],
) -> None:
    """Test entering one parameter first, then second parameter subsequently."""
    _, token = technician_token
    order, p_hgb, p_wbc = clinical_setup

    # First entry: HGB only
    res1 = await client.post(
        f"/api/v1/orders/{order.id}/results",
        json={"results": [{"parameter_id": str(p_hgb.id), "value": "14.5"}]},
        headers={"Authorization": f"Bearer {token}"},
    )
    assert res1.status_code == 200
    report_id = res1.json()["data"]["report_id"]

    # Second entry: WBC only
    res2 = await client.post(
        f"/api/v1/orders/{order.id}/results",
        json={"results": [{"parameter_id": str(p_wbc.id), "value": "13000"}]},
        headers={"Authorization": f"Bearer {token}"},
    )
    assert res2.status_code == 200
    assert res2.json()["data"]["report_id"] == report_id

    # Check worksheet reflects both entered values
    ws_res = await client.get(
        f"/api/v1/orders/{order.id}/results/worksheet",
        headers={"Authorization": f"Bearer {token}"},
    )
    ws_data = ws_res.json()["data"]
    params = ws_data["tests"][0]["parameters"]

    hgb_item = next(p for p in params if p["parameter_id"] == str(p_hgb.id))
    assert hgb_item["current_value"] == "14.5"
    assert hgb_item["flag"] == "N"

    wbc_item = next(p for p in params if p["parameter_id"] == str(p_wbc.id))
    assert wbc_item["current_value"] == "13000"
    assert wbc_item["flag"] == "H"
    assert wbc_item["is_abnormal"] is True


@pytest.mark.asyncio
async def test_enter_results_invalid_parameter_rejected(
    client: AsyncClient,
    technician_token: tuple[User, str],
    clinical_setup: tuple[VisitOrder, LabParameter, LabParameter],
) -> None:
    """Test submitting a parameter ID not on the order returns 422."""
    _, token = technician_token
    order, _, _ = clinical_setup

    res = await client.post(
        f"/api/v1/orders/{order.id}/results",
        json={"results": [{"parameter_id": str(uuid4()), "value": "100"}]},
        headers={"Authorization": f"Bearer {token}"},
    )
    assert res.status_code == 422


@pytest.mark.asyncio
async def test_enter_results_verified_report_locked(
    client: AsyncClient,
    technician_token: tuple[User, str],
    clinical_setup: tuple[VisitOrder, LabParameter, LabParameter],
    db_session: AsyncSession,
) -> None:
    """Test entering results on already verified report is rejected."""
    _, token = technician_token
    order, p_hgb, _ = clinical_setup

    # Manually lock report to VERIFIED
    report = Report(
        order_id=order.id,
        version=1,
        status=ReportStatus.VERIFIED,
    )
    db_session.add(report)
    await db_session.commit()

    res = await client.post(
        f"/api/v1/orders/{order.id}/results",
        json={"results": [{"parameter_id": str(p_hgb.id), "value": "14.0"}]},
        headers={"Authorization": f"Bearer {token}"},
    )
    assert res.status_code == 422
    assert "already 'verified'" in res.json()["error"]["message"].lower()


@pytest.mark.asyncio
async def test_package_only_order_worksheet_and_entry(
    client: AsyncClient,
    technician_token: tuple[User, str],
    db_session: AsyncSession,
    sample_lab: Lab,
) -> None:
    """Regression (ORD/26/000001): package-booked panels appear in the worksheet
    and accept entry even with zero order_test rows."""
    from app.models.order import OrderPackage
    from app.models.package import TestPackage, TestPackageItem

    _, token = technician_token
    headers = {"Authorization": f"Bearer {token}"}

    patient = Patient(
        lab_id=sample_lab.id,
        patient_code="P26-00099",
        name="Package Patient",
        gender=Gender.FEMALE,
        date_of_birth=date(1990, 1, 1),
        phone="9851000099",
    )
    db_session.add(patient)
    cat = LabCategory(lab_id=sample_lab.id, name="Biochemistry")
    db_session.add(cat)
    await db_session.flush()

    test = LabTest(
        lab_id=sample_lab.id,
        category_id=cat.id,
        name="Fasting Blood Glucose",
        code="FBS",
        result_type=LabResultType.NUMERIC,
        price=Decimal("150.00"),
    )
    db_session.add(test)
    await db_session.flush()
    param = LabParameter(test_id=test.id, name="Glucose (Fasting)", unit="mg/dL", sort_order=1)
    db_session.add(param)
    await db_session.flush()

    pkg = TestPackage(lab_id=sample_lab.id, name="Sugar Panel", code="PKG-SUGAR", price=Decimal("150.00"))
    db_session.add(pkg)
    await db_session.flush()
    db_session.add(TestPackageItem(package_id=pkg.id, test_id=test.id, sort_order=0))

    order = VisitOrder(
        lab_id=sample_lab.id,
        patient_id=patient.id,
        order_number="ORD/26/000999",
        status=OrderStatus.SAMPLE_COLLECTED,
    )
    db_session.add(order)
    await db_session.flush()
    db_session.add(OrderPackage(order_id=order.id, package_id=pkg.id, price_at_order=pkg.price))
    await db_session.commit()

    ws = await client.get(f"/api/v1/orders/{order.id}/results/worksheet", headers=headers)
    assert ws.status_code == 200
    tests = ws.json()["data"]["tests"]
    assert [t["test_code"] for t in tests] == ["FBS"]
    assert [p["parameter_name"] for p in tests[0]["parameters"]] == ["Glucose (Fasting)"]

    entry = await client.post(
        f"/api/v1/orders/{order.id}/results",
        json={"results": [{"parameter_id": str(param.id), "value": "95"}]},
        headers=headers,
    )
    assert entry.status_code == 200, entry.text
    assert entry.json()["data"]["total_parameters_entered"] == 1


@pytest.mark.asyncio
async def test_rejected_rework_creates_version_with_audit(
    client: AsyncClient,
    technician_token: tuple[User, str],
    db_session: AsyncSession,
    clinical_setup: tuple[VisitOrder, LabParameter, LabParameter],
) -> None:
    """Reject → re-enter forks v2 (v1 preserved) and logs each review decision."""
    from sqlalchemy import select

    from app.models.audit import AuditLog

    _, token = technician_token
    order, p_hgb, _ = clinical_setup
    headers = {"Authorization": f"Bearer {token}"}

    entered = await client.post(
        f"/api/v1/orders/{order.id}/results",
        json={"results": [{"parameter_id": str(p_hgb.id), "value": "9.0"}]},
        headers=headers,
    )
    assert entered.status_code == 200
    report_id = entered.json()["data"]["report_id"]

    submitted = await client.post(f"/api/v1/reports/{report_id}/submit", json={}, headers=headers)
    assert submitted.status_code == 200

    rejected = await client.post(
        f"/api/v1/reports/{report_id}/reject", json={"reason": "Recheck hemoglobin"}, headers=headers
    )
    assert rejected.status_code == 200
    assert rejected.json()["data"]["status"] == "rejected"

    reworked = await client.post(
        f"/api/v1/orders/{order.id}/results",
        json={"results": [{"parameter_id": str(p_hgb.id), "value": "13.5"}]},
        headers=headers,
    )
    assert reworked.status_code == 200
    assert reworked.json()["data"]["report_id"] != report_id

    v2 = await client.get(f"/api/v1/reports/{reworked.json()['data']['report_id']}", headers=headers)
    assert v2.status_code == 200
    assert v2.json()["data"]["version"] == 2
    assert v2.json()["data"]["previous_report_id"] == report_id

    actions = (
        (await db_session.execute(select(AuditLog.action).where(AuditLog.target_id == str(report_id))))
        .scalars()
        .all()
    )
    assert "REPORT_SUBMITTED" in actions
    assert "REPORT_REJECTED" in actions


@pytest.mark.asyncio
async def test_scoped_order_worksheet_and_entry(
    client: AsyncClient,
    technician_token: tuple[User, str],
    db_session: AsyncSession,
    clinical_setup: tuple[VisitOrder, LabParameter, LabParameter],
) -> None:
    """Analyte-scoped orders expose only scoped params in worksheet + entry."""
    _, token = technician_token
    headers = {"Authorization": f"Bearer {token}"}

    # New order scoped to WBC only (Hemoglobin excluded).
    order = VisitOrder(
        lab_id=clinical_setup[0].lab_id,
        patient_id=clinical_setup[0].patient_id,
        order_number="ORD/26/000777",
        status=OrderStatus.SAMPLE_COLLECTED,
    )
    db_session.add(order)
    await db_session.flush()
    wbc = clinical_setup[2]
    from app.models.order import OrderTest

    test_id = wbc.test_id
    db_session.add(
        OrderTest(
            order_id=order.id,
            test_id=test_id,
            price_at_order=Decimal("450.00"),
            status=OrderTestStatus.DRAFT,
            selected_parameter_ids=[str(wbc.id)],
        )
    )
    await db_session.commit()

    ws = await client.get(f"/api/v1/orders/{order.id}/results/worksheet", headers=headers)
    assert ws.status_code == 200
    params = ws.json()["data"]["tests"][0]["parameters"]
    assert [p["parameter_name"] for p in params] == ["White Blood Cells"]

    # Out-of-scope entry is rejected.
    hgb_param = (
        await db_session.execute(
            select(LabParameter).where(LabParameter.test_id == test_id, LabParameter.name == "Hemoglobin")
        )
    ).scalar_one()
    bad = await client.post(
        f"/api/v1/orders/{order.id}/results",
        json={"results": [{"parameter_id": str(hgb_param.id), "value": "14.0"}]},
        headers=headers,
    )
    assert bad.status_code == 422


@pytest.mark.asyncio
async def test_cancelled_panel_cannot_reappear_through_package(
    client: AsyncClient,
    technician_token: tuple[User, str],
    clinical_setup: tuple[VisitOrder, LabParameter, LabParameter],
    db_session: AsyncSession,
) -> None:
    from app.models.order import OrderPackage
    from app.models.package import TestPackage, TestPackageItem

    order, parameter, _ = clinical_setup
    row = await db_session.scalar(select(OrderTest).where(OrderTest.order_id == order.id))
    row.status = OrderTestStatus.CANCELLED
    package = TestPackage(lab_id=order.lab_id, name="Cancelled Panel Package", code="CANCELLED", price=100)
    db_session.add(package)
    await db_session.flush()
    db_session.add(TestPackageItem(package_id=package.id, test_id=parameter.test_id, sort_order=0))
    db_session.add(OrderPackage(order_id=order.id, package_id=package.id, price_at_order=100))
    await db_session.commit()
    headers = {"Authorization": f"Bearer {technician_token[1]}"}

    worksheet = await client.get(f"/api/v1/orders/{order.id}/results/worksheet", headers=headers)
    assert worksheet.status_code == 200
    assert worksheet.json()["data"]["tests"] == []
    entry = await client.post(
        f"/api/v1/orders/{order.id}/results",
        json={"results": [{"parameter_id": str(parameter.id), "value": "14"}]},
        headers=headers,
    )
    assert entry.status_code == 422
    assert await db_session.scalar(select(Report.id).where(Report.order_id == order.id)) is None
