from __future__ import annotations

import ast
from pathlib import Path


MAX_CLASS_LINES = 800
SERVER_SOURCE_ROOT = Path(__file__).resolve().parents[1] / "src" / "app"


def iter_python_source_files(root: Path) -> list[Path]:
    ignored_parts = {"__pycache__", "x_financial_server.egg-info"}
    return sorted(
        path
        for path in root.rglob("*.py")
        if not ignored_parts.intersection(path.parts)
    )


def test_python_classes_do_not_exceed_800_lines() -> None:
    oversized_classes: list[str] = []

    for path in iter_python_source_files(SERVER_SOURCE_ROOT):
        tree = ast.parse(path.read_text(encoding="utf-8"))
        for node in ast.walk(tree):
            if isinstance(node, ast.ClassDef) and node.end_lineno is not None:
                line_count = node.end_lineno - node.lineno + 1
                if line_count > MAX_CLASS_LINES:
                    relative_path = path.relative_to(SERVER_SOURCE_ROOT.parents[1])
                    oversized_classes.append(
                        f"{relative_path}:{node.lineno} {node.name} ({line_count} lines)"
                    )

    assert oversized_classes == []
