import pytest

from tests.unit_tests.rag.asserts_intent_router import (
    assert_domain_layer_prefixes,
    assert_domains,
    assert_file_only_scope,
    assert_has_file_path,
    assert_intent,
    assert_no_symbol_keyword,
    assert_no_symbol_leakage_from_paths,
    assert_spans_valid,
    assert_sub_intent,
    assert_test_policy,
)
from tests.unit_tests.rag.intent_router_testkit import run_sequence

pytestmark = pytest.mark.intent_router


def test_invariant_code_file_path_with_canonical_key_term() -> None:
    result = run_sequence(["Уточни по файлу app/core/config.py"])[0]

    assert_intent(result, "CODE_QA")
    assert_has_file_path(result, "app/core/config.py")
    assert_file_only_scope(result, "app/core/config.py")
    key_terms = [anchor.value for anchor in result.query_plan.anchors if anchor.type == "KEY_TERM"]
    assert "файл" in key_terms
    assert "файлу" not in key_terms
    assert_spans_valid(result)
    assert_domain_layer_prefixes(result)


def test_invariant_open_file_for_specified_file_phrase_uses_narrow_layers() -> None:
    result = run_sequence(["Уточни по файлу app/core/config.py"])[0]

    assert_intent(result, "CODE_QA")
    assert_sub_intent(result, "OPEN_FILE")
    assert_file_only_scope(result, "app/core/config.py")
    layer_ids = [item.layer_id for item in result.retrieval_spec.layer_queries]
    assert layer_ids == ["C0_SOURCE_CHUNKS"]
    assert result.evidence_policy.require_flow is False


def test_invariant_inline_code_span_routes_to_code_and_extracts_symbol() -> None:
    result = run_sequence(["Уточни по коду `def build(x): return x`"])[0]

    assert_intent(result, "CODE_QA")
    assert_spans_valid(result)
    assert_no_symbol_keyword(result)
    symbols = [anchor.value for anchor in result.query_plan.anchors if anchor.type == "SYMBOL"]
    key_terms = [anchor.value for anchor in result.query_plan.anchors if anchor.type == "KEY_TERM"]
    assert "build" in symbols
    assert "def" in key_terms


def test_invariant_docs_cyrillic_path_with_quotes() -> None:
    result = run_sequence(["Что сказано в «docs/архитектура.md»?"])[0]

    assert_intent(result, "DOCS_QA")
    assert_sub_intent(result, "EXPLAIN")
    assert_domains(result, ["DOCS"])
    assert "docs/архитектура.md" in result.query_plan.normalized
    assert_has_file_path(result, "docs/архитектура.md")
    assert any(anchor.type == "DOC_REF" for anchor in result.query_plan.anchors)
    assert result.retrieval_spec.filters.doc_kinds == []
    assert_spans_valid(result)
    assert_domain_layer_prefixes(result)


def test_invariant_file_check_phrase_not_project_misc() -> None:
    result = run_sequence(["Проверь app/modules/rag/explain/intent_builder.py и объясни"])[0]

    assert_intent(result, "CODE_QA")
    assert_domains(result, ["CODE"])
    assert_no_symbol_leakage_from_paths(result)
    assert_domain_layer_prefixes(result)


def test_invariant_tests_include_routing() -> None:
    result = run_sequence(["Где тесты на ConfigManager?"])[0]

    assert_intent(result, "CODE_QA")
    assert_test_policy(result, "INCLUDE")
    symbols = [anchor.value for anchor in result.query_plan.anchors if anchor.type == "SYMBOL"]
    key_terms = [anchor.value for anchor in result.query_plan.anchors if anchor.type == "KEY_TERM"]
    assert "ConfigManager" in symbols
    assert "тест" in key_terms


def test_invariant_keyword_hints_and_expansions_for_function_identifier() -> None:
    result = run_sequence(["Теперь объясни функцию load_config"])[0]

    assert_intent(result, "CODE_QA")
    assert "load_config" in result.query_plan.keyword_hints
    assert "функция" not in result.query_plan.keyword_hints
    assert "def" not in result.query_plan.expansions


def test_invariant_open_file_sub_intent_uses_narrow_retrieval_profile() -> None:
    result = run_sequence(["Открой файл app/core/config.py"])[0]

    assert_intent(result, "CODE_QA")
    assert_sub_intent(result, "OPEN_FILE")
    assert_file_only_scope(result, "app/core/config.py")
    layer_ids = [item.layer_id for item in result.retrieval_spec.layer_queries]
    assert "C0_SOURCE_CHUNKS" in layer_ids
    assert "C1_SYMBOL_CATALOG" not in layer_ids
    assert "C2_DEPENDENCY_GRAPH" not in layer_ids
    assert "C3_ENTRYPOINTS" not in layer_ids
    assert result.evidence_policy.require_flow is False


def test_invariant_docs_question_routes_to_docs() -> None:
    result = run_sequence(["Что сказано в документации?"])[0]

    assert_intent(result, "DOCS_QA")
    assert_domains(result, ["DOCS"])
    assert_domain_layer_prefixes(result)
    assert result.query_plan.keyword_hints
    assert any(item in result.query_plan.expansions for item in result.query_plan.keyword_hints)
