from __future__ import annotations

from grantflow.eval.harness import compute_state_metrics


def test_compute_state_metrics_splits_fallback_namespace_from_rag_low_confidence():
    metrics = compute_state_metrics(
        {
            "toc_validation": {"valid": True},
            "toc_draft": {"toc": {}},
            "logframe_draft": {"indicators": []},
            "critic_notes": {
                "fatal_flaws": [
                    {"source": "llm", "label": "CAUSAL_LINK_DETAIL", "message": "Add causal chain detail."},
                    {"source": "llm", "label": "CAUSAL_LINK_DETAIL", "message": "Clarify assumptions in chain."},
                    {
                        "source": "llm",
                        "label": "BASELINE_TARGET_MISSING",
                        "message": "Baseline and target missing for indicator.",
                    },
                    {"source": "rules", "label": "IGNORE_ME", "message": "Rule-based structural mismatch."},
                ],
                "llm_advisory_diagnostics": {
                    "advisory_applies": True,
                    "candidate_label_counts": {
                        "CAUSAL_LINK_DETAIL": 2,
                        "BASELINE_TARGET_MISSING": 1,
                    },
                },
            },
            "citations": [
                {
                    "stage": "architect",
                    "used_for": "toc_claim",
                    "statement_path": "toc.project_goal",
                    "citation_type": "fallback_namespace",
                    "citation_confidence": 0.1,
                    "doc_id": "doc-1",
                    "retrieval_rank": 1,
                    "retrieval_confidence": 0.2,
                },
                {
                    "stage": "architect",
                    "used_for": "toc_claim",
                    "statement_path": "toc.objectives[0].description",
                    "citation_type": "rag_low_confidence",
                    "citation_confidence": 0.2,
                    "doc_id": "doc-2",
                    "retrieval_rank": 2,
                    "retrieval_confidence": 0.4,
                },
                {"stage": "mel", "citation_type": "rag_result", "citation_confidence": 0.8},
            ],
        }
    )
    assert metrics["architect_rag_enabled"] is True
    assert metrics["citations_total"] == 3
    assert metrics["low_confidence_citation_count"] == 2
    assert metrics["rag_low_confidence_citation_count"] == 1
    assert metrics["fallback_namespace_citation_count"] == 1
    assert metrics["strategy_reference_citation_count"] == 0
    assert metrics["retrieval_grounded_citation_count"] == 2
    assert metrics["non_retrieval_citation_count"] == 1
    assert metrics["non_retrieval_citation_rate"] == 0.3333
    assert metrics["retrieval_grounded_citation_rate"] == 0.6667
    assert metrics["doc_id_present_citation_count"] == 2
    assert metrics["doc_id_present_citation_rate"] == 0.6667
    assert metrics["retrieval_rank_present_citation_count"] == 2
    assert metrics["retrieval_rank_present_citation_rate"] == 0.6667
    assert metrics["retrieval_confidence_present_citation_count"] == 3
    assert metrics["retrieval_confidence_present_citation_rate"] == 1.0
    assert metrics["retrieval_metadata_complete_citation_count"] == 2
    assert metrics["retrieval_metadata_complete_citation_rate"] == 0.6667
    assert metrics["architect_claim_citation_count"] == 2
    assert metrics["architect_key_claim_coverage_ratio"] == 1.0
    assert metrics["architect_fallback_claim_ratio"] == 0.5
    assert metrics["traceability_complete_citation_count"] == 0
    assert metrics["traceability_partial_citation_count"] == 2
    assert metrics["traceability_missing_citation_count"] == 1
    assert metrics["traceability_gap_citation_count"] == 3
    assert metrics["traceability_gap_citation_rate"] == 1.0
    assert metrics["llm_finding_label_counts"]["CAUSAL_LINK_DETAIL"] == 2
    assert metrics["llm_finding_label_counts"]["BASELINE_TARGET_MISSING"] == 1
    assert metrics["llm_advisory_applied_label_counts"]["CAUSAL_LINK_DETAIL"] == 2
    assert metrics["llm_advisory_applied_label_counts"]["BASELINE_TARGET_MISSING"] == 1
    assert metrics["llm_advisory_rejected_label_counts"] == {}


def test_compute_state_metrics_preserves_architect_rag_flag():
    metrics = compute_state_metrics(
        {
            "architect_rag_enabled": False,
            "toc_validation": {"valid": True},
            "toc_draft": {"toc": {}},
            "logframe_draft": {"indicators": []},
            "citations": [],
        }
    )
    assert metrics["architect_rag_enabled"] is False


def test_compute_state_metrics_tracks_strategy_reference_separately():
    metrics = compute_state_metrics(
        {
            "toc_validation": {"valid": True},
            "toc_draft": {"toc": {}},
            "logframe_draft": {"indicators": []},
            "citations": [
                {"stage": "architect", "citation_type": "strategy_reference", "citation_confidence": 0.75},
                {"stage": "mel", "citation_type": "strategy_reference", "citation_confidence": 0.75},
                {"stage": "architect", "citation_type": "rag_claim_support", "citation_confidence": 0.9},
            ],
        }
    )
    assert metrics["citations_total"] == 3
    assert metrics["fallback_namespace_citation_count"] == 0
    assert metrics["strategy_reference_citation_count"] == 2
    assert metrics["retrieval_grounded_citation_count"] == 1
    assert metrics["non_retrieval_citation_count"] == 2
    assert metrics["non_retrieval_citation_rate"] == 0.6667


def test_compute_state_metrics_normalizes_legacy_alias_string_findings():
    metrics = compute_state_metrics(
        {
            "toc_validation": {"valid": True},
            "toc_draft": {"toc": {}},
            "logframe_draft": {"indicators": []},
            "critic_fatal_flaws": [
                "Missing baseline for indicator set.",
            ],
            "citations": [],
        }
    )
    assert metrics["fatal_flaw_count"] == 1
    assert metrics["high_severity_fatal_flaw_count"] == 0
    assert metrics["llm_finding_label_counts"] == {}
