from dataclasses import replace

import numpy as np

from m3m_disease.features import FEATURE_NAMES
from m3m_disease.inference import ALLOWED_OUTPUT_STATUSES, infer_capture, infer_features


def test_failed_qc_emits_only_rejected_qc(trained_bundle):
    features = trained_bundle["records"][0]["features"]
    result = infer_features(
        trained_bundle["model"],
        features,
        qc_receipt={"passed": False, "failures": ["registration"]},
        sample_id="S01",
    )
    assert result["status"] == "REJECTED_QC"
    assert result["probability"] is None
    assert result["automationAuthorized"] is False


def test_out_of_distribution_features_fail_closed(trained_bundle):
    model = trained_bundle["model"]
    features = {
        name: float(mean + 100 * scale)
        for name, mean, scale in zip(FEATURE_NAMES, model.mean, model.scale)
    }
    result = infer_features(model, features, qc_receipt={"passed": True}, sample_id="OOD")
    assert result["status"] == "REJECTED_OOD"
    assert result["diseaseConfirmed"] is False


def test_between_thresholds_abstains_to_human_review(trained_bundle):
    model = replace(trained_bundle["model"], lowThreshold=0.0, highThreshold=1.0)
    features = trained_bundle["records"][0]["features"]
    result = infer_features(model, features, qc_receipt={"passed": True}, sample_id="UNCERTAIN")
    assert result["status"] == "REVIEW_REQUIRED"
    assert result["abstained"] is True
    assert "human_review" in result["reason"]


def test_capture_inference_receipt_uses_closed_status_vocabulary(tmp_path, trained_bundle):
    receipt = infer_capture(
        trained_bundle["model"],
        trained_bundle["manifests"][0],
        output_path=tmp_path / "receipt.json",
    )
    assert receipt["status"] in ALLOWED_OUTPUT_STATUSES
    assert receipt["fieldPerformanceClaimed"] is False
    assert receipt["treatmentRecommendationPresent"] is False
    assert receipt["patches"]


def test_all_published_patch_statuses_are_allowed(tmp_path, trained_bundle):
    receipt = infer_capture(trained_bundle["model"], trained_bundle["manifests"][1])
    assert {patch["status"] for patch in receipt["patches"]} <= set(ALLOWED_OUTPUT_STATUSES)
    assert all(patch["automationAuthorized"] is False for patch in receipt["patches"])
