"""Tests for Q17 minor-exploitation signal and calibration-derived harm_type."""

from __future__ import annotations

from moralstack.models.risk.calibration import (
    _parse_verification_questions,
    merge_mini_estimator_results,
    parse_risk_dict,
)
from moralstack.orchestration.refusal_context import classify_refusal_focus


def _signal_base(**overrides: str) -> dict[str, str]:
    base = {
        "q1_confidential": "no",
        "q2_unauthorized": "no",
        "q3_breach": "no",
        "q4_fraud": "no",
        "q5_physical": "no",
        "q6_illegal_items": "no",
        "q7_only_emotional": "no",
        "q8_self_harm_suicide": "no",
        "q9_cyber_malware": "no",
        "q10_weapons_explosives_toxins": "no",
        "q11_privacy_doxxing_stalking": "no",
        "q12_medical_harmful": "no",
        "q13_protected_class_targeting": "no",
        "q14_reputational_harm": "no",
        "q15_deceptive_online_campaign": "no",
        "q16_harassment_smear_campaign": "no",
        "q17_minor_exploitation": "no",
        "domain_sensitivity": "MEDIUM",
    }
    base.update(overrides)
    return base


def _intent_base(**overrides) -> dict:
    base = {
        "detected_language": "en",
        "intent_to_harm": "yes",
        "requested_instructions": "yes",
        "intent_operational": True,
        "request_type": "clear_harm",
        "harm_type": "",
        "intent_clarity": "HIGH",
        "stated_personal_bias": "no",
        "seeks_norm_circumvention": "no",
        "rationale": "Operational grooming/contact playbook requested.",
    }
    base.update(overrides)
    return base


def _operational_base(**overrides) -> dict:
    base = {
        "operational_risk": "HIGH",
        "risk_score": 0.9,
        "confidence": 0.95,
        "misuse_plausibility": "HIGH",
        "actionability_risk": "HIGH",
        "risk_policy_action": "DENY",
        "rationale": "High operational exploitation risk.",
    }
    base.update(overrides)
    return base


def test_parse_verification_questions_q17_defaults_and_yes() -> None:
    assert _parse_verification_questions({}).q17_minor_exploitation is False
    q = _parse_verification_questions({"q17_minor_exploitation": "yes"})
    assert q.q17_minor_exploitation is True


def test_merge_propagates_q17_from_signals() -> None:
    merged = merge_mini_estimator_results(
        _intent_base(),
        _signal_base(q17_minor_exploitation="yes"),
        _operational_base(),
    )
    assert merged.get("q17_minor_exploitation") == "yes"


def test_q17_sets_child_exploitation_harm_type_and_signal_label() -> None:
    data = _signal_base(q17_minor_exploitation="yes")
    data.update(_intent_base())
    data.update(_operational_base())
    parsed = parse_risk_dict(data)
    assert parsed.harm_type == "child_exploitation"
    assert "Q17:minor_exploitation" in parsed.signals
    assert parsed.q17_minor_exploitation is True


def test_weapons_priority_overrides_q17_harm_type() -> None:
    data = _signal_base(q17_minor_exploitation="yes", q10_weapons_explosives_toxins="yes")
    data.update(_intent_base())
    data.update(_operational_base())
    parsed = parse_risk_dict(data)
    assert parsed.harm_type == "weapons"
    assert "Q17:minor_exploitation" in parsed.signals


def test_classify_refusal_focus_minor_signal() -> None:
    focus, _guidance = classify_refusal_focus(
        semantic_signals=["Q17:minor_exploitation"],
        harm_type="child_exploitation",
        request_type="clear_harm",
        operational_risk="HIGH",
        requested_instructions=True,
        intent_to_harm=True,
        intent_operational=True,
    )
    assert focus == "child_safety_minor_protection"
