from grantflow.swarm.critic_rules import evaluate_rule_based_critic
from grantflow.tests.critic_rules_grounding_quality_helpers import state_with_updates


def test_rule_based_critic_flags_fallback_dominant_architect_grounding_when_rag_enabled():
    state = state_with_updates(
        architect_rag_enabled=True,
        toc_draft={
            "toc": {
                "project_goal": "Improve services",
                "objectives": [
                    {"title": "Objective 1", "description": "Outcome pathway one"},
                    {"title": "Objective 2", "description": "Outcome pathway two"},
                ],
            }
        },
        logframe_draft={"indicators": [{"indicator_id": "IND_001"}]},
        citations=[
            {
                "stage": "architect",
                "used_for": "toc_claim",
                "statement_path": "toc.project_goal",
                "citation_type": "fallback_namespace",
                "citation_confidence": 0.1,
                "confidence_threshold": 0.4,
            },
            {
                "stage": "architect",
                "used_for": "toc_claim",
                "statement_path": "toc.objectives[0].description",
                "citation_type": "fallback_namespace",
                "citation_confidence": 0.1,
                "confidence_threshold": 0.4,
            },
            {
                "stage": "architect",
                "used_for": "toc_claim",
                "statement_path": "toc.objectives[1].description",
                "citation_type": "fallback_namespace",
                "citation_confidence": 0.1,
                "confidence_threshold": 0.4,
            },
            {
                "stage": "mel",
                "label": "doc",
                "used_for": "IND_001",
                "citation_type": "rag_result",
                "citation_confidence": 0.8,
            },
        ],
        toc_generation_meta={
            "claim_coverage": {
                "key_claim_coverage_ratio": 1.0,
                "fallback_claim_ratio": 1.0,
            }
        },
    )

    report = evaluate_rule_based_critic(state)
    checks = [c.model_dump() if hasattr(c, "model_dump") else c.dict() for c in report.checks]
    flaws = [f.model_dump() if hasattr(f, "model_dump") else f.dict() for f in report.fatal_flaws]

    assert any(c["code"] == "TOC_CLAIM_GROUNDING_BALANCE" and c["status"] == "fail" for c in checks)
    assert any(c["code"] == "TOC_CLAIM_TRACEABILITY_GAP" and c["status"] == "fail" for c in checks)
    assert any(c["code"] == "TOC_CLAIM_CONFIDENCE_HIT_RATE" and c["status"] == "fail" for c in checks)
    assert any(f["code"] == "TOC_CLAIM_GROUNDING_FALLBACK_DOMINANT" for f in flaws)
    assert any(f["code"] == "TOC_CLAIM_TRACEABILITY_GAP_CRITICAL" for f in flaws)
    assert any(f["code"] == "TOC_CLAIM_CONFIDENCE_HIT_RATE_CRITICAL" for f in flaws)


def test_rule_based_critic_emits_more_reviewer_oriented_rule_text():
    state = state_with_updates(
        architect_rag_enabled=True,
        toc_draft={
            "toc": {
                "project_goal": "Improve service delivery.",
                "objectives": [
                    {"title": "Objective 1", "description": "TBD"},
                    {"title": "Objective 2", "description": "TBD"},
                ],
            }
        },
        logframe_draft={
            "indicators": [
                {"indicator_id": "IND_001", "baseline": "TBD", "target": "TBD"},
            ]
        },
        citations=[
            {
                "stage": "architect",
                "used_for": "toc_claim",
                "statement_path": "toc.project_goal",
                "citation_type": "fallback_namespace",
                "citation_confidence": 0.1,
                "confidence_threshold": 0.4,
            },
            {
                "stage": "architect",
                "used_for": "toc_claim",
                "statement_path": "toc.objectives[0].description",
                "citation_type": "fallback_namespace",
                "citation_confidence": 0.1,
                "confidence_threshold": 0.4,
            },
            {
                "stage": "architect",
                "used_for": "toc_claim",
                "statement_path": "toc.objectives[1].description",
                "citation_type": "fallback_namespace",
                "citation_confidence": 0.1,
                "confidence_threshold": 0.4,
            },
        ],
        toc_generation_meta={
            "claim_coverage": {
                "key_claim_coverage_ratio": 1.0,
                "fallback_claim_ratio": 1.0,
            }
        },
    )

    report = evaluate_rule_based_critic(state)
    flaws = [f.model_dump() if hasattr(f, "model_dump") else f.dict() for f in report.fatal_flaws]
    by_code = {f["code"]: f for f in flaws}

    assert "reviewers cannot assess" in by_code["TOC_PLACEHOLDER_CONTENT_CRITICAL"]["message"].lower()
    assert (
        "section-specific objective, outcome, and assumption statements"
        in by_code["TOC_PLACEHOLDER_CONTENT_CRITICAL"]["fix_hint"].lower()
    )
    assert (
        "not evidence-backed enough for serious review"
        in by_code["TOC_CLAIM_GROUNDING_FALLBACK_DOMINANT"]["message"].lower()
    )
    assert (
        "concrete, measurable figures" in by_code["LOGFRAME_BASELINE_TARGET_PLACEHOLDERS_CRITICAL"]["fix_hint"].lower()
    )
