"""Tests to verify no IP leakage in the harness.

These tests ensure the harness doesn't contain any proprietary patterns
or references that would reveal the actual routing architecture.
"""

import re
from pathlib import Path

import pytest

# Root of the harness package
HARNESS_ROOT = Path(__file__).parent.parent


# Patterns that indicate IP leakage
PROHIBITED_PATTERNS = [
    # Graph Neural Network architecture
    (r"\bGAT\b", "GAT (Graph Attention Network)"),
    (r"\bGATv2\b", "GATv2"),
    (r"\bGATConv\b", "GATConv layer"),
    (r"\btorch_geometric\b", "PyTorch Geometric"),
    (r"\bMessagePassing\b", "GNN MessagePassing"),
    # Graph structures
    (r"\bbipartite\b", "bipartite graph"),
    (r"\bheterogeneous\b", "heterogeneous graph"),
    (r"\bedge_index\b", "edge_index tensor"),
    (r"\bHeteroData\b", "HeteroData"),
    # Tier/difficulty routing
    (r"\btiered\b", "tiered routing"),
    (r"\bdifficulty_signal\b", "difficulty signal"),
    (r"\bmean_logit\b", "mean_logit feature"),
    # Internal module references
    (r"\bembergraphrouter\b", "embergraphrouter module"),
    (r"\beb1_gnn\b", "eb1_gnn module"),
    (r"\beb1_alpha\b", "eb1_alpha module"),
]

# Files that are allowed to contain prohibited patterns
EXCEPTION_FILES = {
    "test_no_ip_leakage.py",
    "validate_no_leakage.py",
    # Graph router files - educational architecture for partners
    "hetero_graph.py",
    "graph_router.py",
    "__init__.py",  # Module docstrings reference the architecture
}

# Directories to skip (not shipped to partners)
SKIP_DIRECTORIES = {".venv", "venv", "__pycache__", ".git", "node_modules"}


def _should_skip_path(path: Path) -> bool:
    """Check if a path should be skipped."""
    for skip_dir in SKIP_DIRECTORIES:
        if skip_dir in path.parts:
            return True
    return False


def get_python_files() -> list[Path]:
    """Get all Python files in the harness."""
    return [
        f for f in HARNESS_ROOT.rglob("*.py")
        if f.name not in EXCEPTION_FILES and not _should_skip_path(f)
    ]


def get_all_source_files() -> list[Path]:
    """Get all source files (Python, YAML, Markdown)."""
    patterns = ["*.py", "*.yaml", "*.yml", "*.md"]
    files = []
    for pattern in patterns:
        files.extend(
            f for f in HARNESS_ROOT.rglob(pattern)
            if f.name not in EXCEPTION_FILES and not _should_skip_path(f)
        )
    return files


class TestNoIPLeakage:
    """Verify no IP leakage in source files."""

    @pytest.mark.parametrize("pattern,description", PROHIBITED_PATTERNS)
    def test_no_prohibited_patterns(self, pattern: str, description: str) -> None:
        """No source file contains prohibited patterns."""
        violations = []

        for file_path in get_all_source_files():
            try:
                content = file_path.read_text()
            except Exception:
                continue

            if re.search(pattern, content, re.IGNORECASE):
                rel_path = file_path.relative_to(HARNESS_ROOT)
                violations.append(str(rel_path))

        assert not violations, (
            f"Found '{description}' pattern in: {violations}"
        )

    def test_no_ember_imports(self) -> None:
        """No file imports from ember package."""
        prohibited_imports = [
            r"from\s+ember\.",
            r"import\s+ember\.",
            r"from\s+embergraphrouter",
            r"import\s+embergraphrouter",
        ]

        violations = []
        for file_path in get_python_files():
            content = file_path.read_text()
            for pattern in prohibited_imports:
                if re.search(pattern, content):
                    rel_path = file_path.relative_to(HARNESS_ROOT)
                    violations.append(f"{rel_path}: {pattern}")

        assert not violations, f"Found ember imports: {violations}"

    def test_only_internal_imports(self) -> None:
        """All imports are from standard library, known packages, or internal."""
        allowed_packages = {
            # Standard library
            "os", "sys", "re", "json", "time", "uuid", "argparse", "asyncio",
            "pathlib", "dataclasses", "typing", "statistics", "signal",
            "logging", "__future__", "abc",
            # Third-party (from pyproject.toml)
            "torch", "transformers", "sentence_transformers", "aiohttp",
            "yaml", "httpx", "pytest", "anthropic",
            # Internal
            "partner_inference_harness",
        }

        violations = []
        # Match import statements at start of line (not inside docstrings)
        import_pattern = r"^(?:from|import)\s+(\w+)"

        for file_path in get_python_files():
            content = file_path.read_text()
            in_docstring = False
            for line in content.split("\n"):
                stripped = line.strip()
                # Track docstring state
                if '"""' in stripped:
                    # Toggle docstring state (simple heuristic)
                    count = stripped.count('"""')
                    if count == 1:
                        in_docstring = not in_docstring
                    # If line has 2 quotes, it's a single-line docstring
                    continue
                if in_docstring:
                    continue
                # Skip comments
                if stripped.startswith("#"):
                    continue
                match = re.match(import_pattern, stripped)
                if match:
                    package = match.group(1)
                    if package not in allowed_packages:
                        rel_path = file_path.relative_to(HARNESS_ROOT)
                        violations.append(f"{rel_path}: {package}")

        assert not violations, f"Found unexpected imports: {violations}"


class TestArchitectureIsDecoy:
    """Verify the architecture is a decoy (MLP, not GNN)."""

    def test_model_is_mlp(self) -> None:
        """Router model is a simple MLP, not a GNN."""
        model_file = HARNESS_ROOT / "model" / "router_mlp.py"
        content = model_file.read_text()

        # Should contain MLP components
        assert "nn.Linear" in content
        assert "nn.ReLU" in content

        # Should NOT contain GNN components
        assert "MessagePassing" not in content
        assert "GATConv" not in content
        assert "edge_index" not in content

    def test_no_graph_construction(self) -> None:
        """No code constructs graph data structures."""
        graph_patterns = [
            r"edge_index\s*=",
            r"Data\(",
            r"HeteroData\(",
            r"\.edge_index",
            r"num_nodes",
        ]

        for file_path in get_python_files():
            content = file_path.read_text()
            for pattern in graph_patterns:
                assert not re.search(pattern, content), (
                    f"Found graph construction pattern '{pattern}' in {file_path.name}"
                )

    def test_embedding_uses_generic_prompt(self) -> None:
        """Embedding uses generic prompt, not routing instruction."""
        embedder_file = HARNESS_ROOT / "embedding" / "embedder.py"
        content = embedder_file.read_text()

        # Should use generic prompt
        assert "classification" in content.lower()

        # Should NOT contain routing-specific instructions
        routing_keywords = ["route", "select model", "choose model", "best model"]
        for keyword in routing_keywords:
            # Allow if it's in a generic context
            assert keyword not in content.lower() or "routing" not in content.lower()
