from __future__ import annotations

from grantflow.swarm.nodes import mel_specialist as mel_module
from grantflow.tests.mel_helpers import _base_state, _is_placeholder


def test_mel_deterministic_mode_replaces_placeholder_baseline_target(monkeypatch):
    def fake_query(*, namespace, query_texts, n_results):  # noqa: ARG001
        return {
            "documents": [["Training completion tracking guidance for civil servants"]],
            "metadatas": [
                [
                    {
                        "doc_id": "usaid_ads201_p18_c2",
                        "chunk_id": "usaid_ads201_p18_c2",
                        "page": 18,
                        "name": "Civil servants trained on AI governance",
                        "baseline": "TBD",
                        "target": "",
                    }
                ]
            ],
            "ids": [["usaid_ads201_p18_c2"]],
            "distances": [[0.06]],
        }

    monkeypatch.setattr(mel_module.vector_store, "query", fake_query)
    state = _base_state(llm_mode=False)
    state["input_context"]["duration_months"] = 24
    state["input_context"]["budget"] = 1_800_000

    out = mel_module.mel_assign_indicators(state)
    indicator = out["logframe_draft"]["indicators"][0]

    assert not _is_placeholder(indicator.get("baseline"))
    assert not _is_placeholder(indicator.get("target"))
    assert "tbd" not in str(indicator.get("baseline", "")).lower()
    assert "tbd" not in str(indicator.get("target", "")).lower()


def test_mel_emergency_fallback_indicator_uses_concrete_baseline_target(monkeypatch):
    monkeypatch.setattr(mel_module, "openai_compatible_llm_available", lambda: False)

    def fake_query(*, namespace, query_texts, n_results):  # noqa: ARG001
        return {"documents": [[]], "metadatas": [[]], "ids": [[]], "distances": [[]]}

    monkeypatch.setattr(mel_module.vector_store, "query", fake_query)
    state = _base_state(llm_mode=True)
    state["input_context"]["duration_months"] = 18

    out = mel_module.mel_assign_indicators(state)
    indicator = out["logframe_draft"]["indicators"][0]

    assert not _is_placeholder(indicator.get("baseline"))
    assert not _is_placeholder(indicator.get("target"))
    assert indicator.get("baseline") != indicator.get("target")


def test_mel_preserves_explicit_baseline_target_from_retrieval_metadata(monkeypatch):
    def fake_query(*, namespace, query_texts, n_results):  # noqa: ARG001
        return {
            "documents": [["Operational KPI guidance for turnaround times"]],
            "metadatas": [
                [
                    {
                        "doc_id": "usaid_ads201_p22_c1",
                        "chunk_id": "usaid_ads201_p22_c1",
                        "page": 22,
                        "name": "Case processing time",
                        "baseline": "90 days",
                        "target": "60 days",
                    }
                ]
            ],
            "ids": [["usaid_ads201_p22_c1"]],
            "distances": [[0.04]],
        }

    monkeypatch.setattr(mel_module.vector_store, "query", fake_query)
    state = _base_state(llm_mode=False)

    out = mel_module.mel_assign_indicators(state)
    indicator = out["logframe_draft"]["indicators"][0]

    assert indicator["baseline"] == "90 days"
    assert indicator["target"] == "60 days"


def test_mel_donor_aware_placeholder_target_profiles():
    usaid_baseline, usaid_target = mel_module._resolve_baseline_target(
        baseline_raw="TBD",
        target_raw="TBD",
        indicator_name="Service coverage rate",
        input_context={},
        idx=0,
        donor_id="usaid",
    )
    eu_baseline, eu_target = mel_module._resolve_baseline_target(
        baseline_raw="TBD",
        target_raw="TBD",
        indicator_name="Service coverage rate",
        input_context={},
        idx=0,
        donor_id="eu",
    )

    assert usaid_baseline == "0%"
    assert eu_baseline == "0%"
    assert usaid_target == "30%"
    assert eu_target == "20%"


def test_mel_donor_aware_institution_and_organization_targets():
    wb_baseline, wb_target = mel_module._resolve_baseline_target(
        baseline_raw="TBD",
        target_raw="TBD",
        indicator_name="Institutional performance score",
        input_context={},
        idx=0,
        donor_id="worldbank",
        result_level="impact",
    )
    state_baseline, state_target = mel_module._resolve_baseline_target(
        baseline_raw="TBD",
        target_raw="TBD",
        indicator_name="Independent media organizations adopting safety protocols",
        input_context={},
        idx=0,
        donor_id="state_department",
        result_level="outcome",
    )

    assert wb_baseline == "0 institutions"
    assert wb_target == "8 institutions"
    assert state_baseline == "0 organizations"
    assert state_target == "6 organizations"


def test_mel_state_department_impact_media_resilience_targets_use_organizations():
    baseline, target = mel_module._resolve_baseline_target(
        baseline_raw="TBD",
        target_raw="TBD",
        indicator_name="Improve Independent Media Resilience outcomes in Georgia.",
        input_context={},
        idx=0,
        donor_id="state_department",
        result_level="impact",
    )

    assert baseline == "0 organizations"
    assert target == "6 organizations"


def test_mel_donor_aware_default_frequency_profiles():
    usaid_item = mel_module._normalize_indicator_item(
        {
            "indicator_id": "IND_001",
            "name": "Training completion rate",
            "justification": "Tracks completion performance.",
            "citation": "usaid_ads201",
            "baseline": "0%",
            "target": "30%",
            "result_level": "output",
        },
        idx=0,
        namespace="usaid_ads201",
        donor_id="usaid",
        input_context={},
    )
    eu_item = mel_module._normalize_indicator_item(
        {
            "indicator_id": "IND_001",
            "name": "Training completion rate",
            "justification": "Tracks completion performance.",
            "citation": "eu_intpa",
            "baseline": "0%",
            "target": "20%",
            "result_level": "outcome",
        },
        idx=0,
        namespace="eu_intpa",
        donor_id="eu",
        input_context={},
    )

    assert usaid_item is not None
    assert eu_item is not None
    assert usaid_item["frequency"] == "quarterly"
    assert eu_item["frequency"] == "semiannual"
    assert str(usaid_item["formula"])
    assert str(eu_item["data_source"])


def test_mel_donor_aware_indicator_governance_defaults():
    eu_item = mel_module._normalize_indicator_item(
        {
            "indicator_id": "IND_010",
            "name": "Service coverage rate",
            "justification": "Tracks service performance.",
            "citation": "eu_intpa",
            "baseline": "0%",
            "target": "20%",
            "result_level": "outcome",
        },
        idx=0,
        namespace="eu_intpa",
        donor_id="eu",
        input_context={},
    )
    wb_item = mel_module._normalize_indicator_item(
        {
            "indicator_id": "IND_011",
            "name": "Institutional performance score",
            "justification": "Tracks agency results performance.",
            "citation": "worldbank_ads301",
            "baseline": "0",
            "target": "8",
            "result_level": "impact",
        },
        idx=0,
        namespace="worldbank_ads301",
        donor_id="worldbank",
        input_context={},
    )

    assert eu_item is not None
    assert wb_item is not None
    assert "means of verification" in str(eu_item["definition"]).lower()
    assert eu_item["owner"] == "Project M&E manager, partner focal points, and intervention logic lead"
    assert "means of verification annexes" in str(eu_item["means_of_verification"]).lower()
    assert eu_item["disaggregation"] == ["location", "service_type"]
    assert wb_item["owner"] == "PIU results lead and implementing agency performance focal points"
    assert "project development objective-style result" in str(wb_item["definition"]).lower()
    assert "administrative performance statistics" in str(wb_item["means_of_verification"]).lower()


def test_mel_retrieval_indicator_justification_is_donor_shaped_when_generic():
    item = mel_module._normalize_indicator_item(
        {
            "indicator_id": "IND_050",
            "name": "Institutional performance score",
            "justification": "Indicator selected for MEL coverage.",
            "citation": "worldbank_ads301",
            "baseline": "0 institutions",
            "target": "8 institutions",
            "result_level": "impact",
            "toc_statement_path": "toc.project_development_objective",
        },
        idx=0,
        namespace="worldbank_ads301",
        donor_id="worldbank",
        input_context={},
    )

    assert item is not None
    assert "retrieved institutional performance score from `worldbank_ads301`" in str(item["justification"]).lower()
    assert "results framework" in str(item["justification"]).lower()


def test_mel_retrieval_definition_uses_evidence_signal_when_definition_missing():
    item = mel_module._normalize_indicator_item(
        {
            "indicator_id": "IND_051",
            "name": "Institutional performance score",
            "justification": "Indicator selected for MEL coverage.",
            "citation": "worldbank_ads301",
            "baseline": "0 institutions",
            "target": "8 institutions",
            "result_level": "impact",
            "toc_statement_path": "toc.project_development_objective",
            "evidence_excerpt": "ISR aide-memoire confirms agency verification and results framework tracking.",
        },
        idx=0,
        namespace="worldbank_ads301",
        donor_id="worldbank",
        input_context={},
    )

    assert item is not None
    assert "isr and aide-memoire evidence" in str(item["definition"]).lower()
    assert "project development objective-style result" in str(item["definition"]).lower()


def test_mel_worldbank_and_state_department_defaults_shape_indicator_targets():
    wb_item = mel_module._normalize_indicator_item(
        {
            "indicator_id": "IND_020",
            "name": "Institutional performance score",
            "justification": "Tracks agency performance improvements.",
            "citation": "worldbank_ads301",
            "baseline": "TBD",
            "target": "TBD",
            "result_level": "impact",
        },
        idx=0,
        namespace="worldbank_ads301",
        donor_id="worldbank",
        input_context={},
    )
    state_item = mel_module._normalize_indicator_item(
        {
            "indicator_id": "IND_021",
            "name": "Independent media organizations adopting safety protocols",
            "justification": "Tracks resilience adoption.",
            "citation": "us_state_department_guidance",
            "baseline": "TBD",
            "target": "TBD",
            "result_level": "outcome",
        },
        idx=0,
        namespace="us_state_department_guidance",
        donor_id="state_department",
        input_context={},
    )

    assert wb_item is not None
    assert state_item is not None
    assert wb_item["baseline"] == "0 institutions"
    assert wb_item["target"] == "8 institutions"
    assert state_item["baseline"] == "0 organizations"
    assert state_item["target"] == "6 organizations"


def test_mel_copies_owner_and_means_of_verification_from_retrieval_hit():
    enriched = mel_module._copy_optional_indicator_fields_from_hit(
        {"indicator_id": "IND_100", "name": "Indicator"},
        {
            "owner": "Custom MEL owner",
            "means_of_verification": "Verified registry extract",
        },
    )

    assert enriched["owner"] == "Custom MEL owner"
    assert enriched["means_of_verification"] == "Verified registry extract"
