"""Generate the code reference pages for Python and Nix APIs."""

from pathlib import Path
from textwrap import dedent

import mkdocs_gen_files
from plumbum import local
from plumbum.commands import CommandNotFound

root = Path(__file__).parent.parent
src = root / "src" / "polytropos"

python_module_titles = {
    "build": "`build`",
    "build/manifest": "`build.manifest`",
    "build/pep517": "`build.pep517`",
    "build/primitives": "`build.primitives`",
    "ph": "`ph`",
    "__main__": "`__main__`",
}


def generate_python_doc(module_path: Path, title: str):
    """Generate a documentation page for a Python module."""
    module_name = module_path.as_posix().replace("/", ".")
    full_module_name = f"polytropos.{module_name}"
    full_doc_path = Path("api") / "python" / f"{module_path.as_posix()}.md"

    with mkdocs_gen_files.open(full_doc_path, "w") as f:
        content = dedent(f"""\
        # {title}

        !!! warning "Private Methods"

            Private methods, if any (those starting with `_`), are documented
            for completeness but do **not** offer any stability guarantees.
            They may change or be removed at any time without notice.

        ::: {full_module_name}
        """)
        print(content, file=f)


def run_nixdoc(nix_file: Path, description: str) -> str | None:
    """Run nixdoc on a file and return the output."""
    try:
        nixdoc_cmd = local["nixdoc"]
        result = nixdoc_cmd[
            "--file",
            str(nix_file),
            "--category",
            "",
            "--description",
            description,
        ].run(retcode=None)
        if result[0] != 0:
            print(f"Warning: nixdoc failed for {nix_file}: {result[2]}")
            return None
        return result[1]
    except CommandNotFound:
        nix = local["nix"]
        result = nix[
            "run",
            "nixpkgs#nixdoc",
            "--",
            "--file",
            str(nix_file),
            "--category",
            "",
            "--description",
            description,
        ].run(retcode=None)
        if result[0] != 0:
            print(f"Warning: nixdoc failed for {nix_file}: {result[2]}")
            return None
        return result[1]


def generate_nix_docs():
    """Generate documentation for Nix files."""
    nix_files = [
        (
            root / "lib" / "default.nix",
            Path("api") / "nix" / "lib.md",
            "Polytropos nix helpers",
        ),
        (
            root / "modules" / "devshell" / "default.nix",
            Path("api") / "nix" / "devshell.md",
            "Devshell module",
        ),
    ]

    for nix_file, doc_path, description in nix_files:
        if not nix_file.exists():
            continue
        output = run_nixdoc(nix_file, description)
        if output:
            with mkdocs_gen_files.open(doc_path, "w") as f:
                print(output, file=f)


generate_python_doc(Path("build"), "`build`")

for path in sorted(src.rglob("*.py")):
    if path.name == "__init__.py":
        continue
    module_path = path.relative_to(src).with_suffix("")
    title = python_module_titles.get(module_path.as_posix(), module_path.name.title())
    generate_python_doc(module_path, title)

generate_nix_docs()
