from __future__ import annotations

import re
from pathlib import Path


ROOT = Path(__file__).resolve().parent
LEGACY_APP = ROOT / "legacydb"
SOURCE = LEGACY_APP / "models.py"
TARGET_DIR = LEGACY_APP / "model_defs"


CLASS_RE = re.compile(r"^class\s+([A-Za-z_][A-Za-z0-9_]*)\(models\.Model\):", re.M)
FK_DIRECT_RE = re.compile(r"(ForeignKey|OneToOneField|ManyToManyField)\((\s*)([A-Z][A-Za-z0-9_]*)(\s*,)")


def to_snake(name: str) -> str:
    return re.sub(r"(?<!^)(?=[A-Z])", "_", name).lower()


def split_models() -> None:
    text = SOURCE.read_text(encoding="utf-8")
    matches = list(CLASS_RE.finditer(text))
    if not matches:
        raise RuntimeError("No model classes found in legacydb/models.py")

    TARGET_DIR.mkdir(exist_ok=True)

    class_names: list[str] = []

    for i, match in enumerate(matches):
        class_name = match.group(1)
        start = match.start()
        end = matches[i + 1].start() if i + 1 < len(matches) else len(text)
        block = text[start:end].strip() + "\n"

        # Make cross-model references resilient after splitting files.
        block = FK_DIRECT_RE.sub(r"\1(\2'\3'\4", block)

        file_body = "from django.db import models\n\n\n" + block
        file_path = TARGET_DIR / f"{to_snake(class_name)}.py"
        file_path.write_text(file_body, encoding="utf-8")
        class_names.append(class_name)

    init_lines = [f"from .{to_snake(name)} import {name}" for name in class_names]
    init_lines.append("")
    init_lines.append(f"__all__ = [{', '.join(repr(name) for name in class_names)}]")
    (TARGET_DIR / "__init__.py").write_text("\n".join(init_lines) + "\n", encoding="utf-8")

    models_aggregator = "from .model_defs import *  # noqa: F401,F403\n"
    SOURCE.write_text(models_aggregator, encoding="utf-8")

    print(f"Split {len(class_names)} models into {TARGET_DIR}")


if __name__ == "__main__":
    split_models()
