import re
from pathlib import Path


ROOT = Path(__file__).resolve().parents[1]
INVENTORY = ROOT / "docs/memory/code_modularization_inventory_20260430.md"
GUIDE = ROOT / "docs/guides/modularization_governance.md"


def _python_line_counts():
    ignored_parts = {".git", ".venv", "venv", "backups", "tests", "__pycache__", ".pytest_cache"}
    ignored_prefixes = {
        ("docs", "design"),
        ("docs", "design_audit_frontend"),
    }
    for path in ROOT.rglob("*.py"):
        parts = path.relative_to(ROOT).parts
        if any(part in ignored_parts for part in parts):
            continue
        if parts[:2] in ignored_prefixes:
            continue
        if len(parts) >= 2 and parts[0] == ".claude" and parts[1] == "worktrees":
            continue
        with path.open(encoding="utf-8", errors="ignore") as handle:
            yield path.relative_to(ROOT).as_posix(), sum(1 for _ in handle)


def test_large_python_modules_are_tracked_in_modularization_inventory():
    inventory = INVENTORY.read_text(encoding="utf-8")
    large_modules = {
        path: lines
        for path, lines in _python_line_counts()
        if lines >= 800
    }

    assert large_modules, "盤點應至少包含目前既有大檔"
    missing = [
        f"{path} ({lines} lines)"
        for path, lines in sorted(large_modules.items())
        if f"`{path}`" not in inventory
    ]
    assert missing == []


def test_modularization_inventory_line_counts_are_current_enough():
    inventory = INVENTORY.read_text(encoding="utf-8")
    inventory_counts = {
        match.group("path"): int(match.group("lines"))
        for match in re.finditer(
            r"^\|\s*(?P<lines>\d+)\s*\|\s*`(?P<path>[^`]+)`\s*\|",
            inventory,
            re.MULTILINE,
        )
    }
    large_modules = {
        path: lines
        for path, lines in _python_line_counts()
        if lines >= 800
    }

    stale = []
    for path, current_lines in sorted(large_modules.items()):
        recorded_lines = inventory_counts.get(path)
        if recorded_lines is None:
            continue
        allowed_drift = max(50, int(current_lines * 0.1))
        if abs(recorded_lines - current_lines) > allowed_drift:
            stale.append(f"{path}: recorded={recorded_lines}, current={current_lines}")

    assert stale == []


def test_modularization_governance_is_indexed_for_codex_sessions():
    agents = (ROOT / "AGENTS.md").read_text(encoding="utf-8")
    constitution = (ROOT / "CONSTITUTION.md").read_text(encoding="utf-8")
    memory_index = (ROOT / "docs/memory/README.md").read_text(encoding="utf-8")

    assert "docs/guides/modularization_governance.md" in agents
    assert "docs/guides/modularization_governance.md" in constitution
    assert "code_modularization_inventory_20260430.md" in agents
    assert "code_modularization_inventory_20260430.md" in memory_index
    assert GUIDE.exists()
