"""Helpers for cross-platform Makefile targets."""

from __future__ import annotations

import argparse
import os
import re
import subprocess
import sys
import tempfile
from pathlib import Path


HEADER_LINES = [
    "# Generated from pyproject.toml and uv.lock.",
    "# Do not edit manually. Run `make deps-export` to regenerate.",
    "",
]


def _run(command: list[str], *, env: dict[str, str] | None = None) -> None:
    subprocess.run(command, check=True, env=env)


def render_help(makefiles: list[str]) -> None:
    pattern = re.compile(r"^([A-Za-z0-9_-]+):.*## (.+)$")
    entries: list[tuple[str, str]] = []
    for makefile in makefiles:
        for line in Path(makefile).read_text(encoding="utf-8").splitlines():
            match = pattern.match(line)
            if match:
                entries.append((match.group(1), match.group(2)))

    for target, description in sorted(entries):
        print(f"{target:<18} {description}")


def uv_sync(uv_binary: str, venv_path: str) -> None:
    env = os.environ.copy()
    env["VIRTUAL_ENV"] = str(Path(venv_path).resolve())
    _run([uv_binary, "sync", "--active", "--dev", "--locked"], env=env)


def _write_export(destination: Path, export_path: Path) -> None:
    content = export_path.read_text(encoding="utf-8")
    destination.write_text("\n".join(HEADER_LINES) + content, encoding="utf-8")


def deps_export(uv_binary: str) -> None:
    with tempfile.TemporaryDirectory() as temp_dir:
        temp_path = Path(temp_dir)
        runtime_export = temp_path / "requirements-runtime.txt"
        dev_export = temp_path / "requirements-dev.txt"

        _run(
            [
                uv_binary,
                "export",
                "--quiet",
                "--format",
                "requirements.txt",
                "--frozen",
                "--no-dev",
                "--no-editable",
                "--no-emit-project",
                "--no-hashes",
                "--no-header",
                "--output-file",
                str(runtime_export),
            ]
        )
        _run(
            [
                uv_binary,
                "export",
                "--quiet",
                "--format",
                "requirements.txt",
                "--frozen",
                "--only-dev",
                "--no-editable",
                "--no-emit-project",
                "--no-hashes",
                "--no-header",
                "--output-file",
                str(dev_export),
            ]
        )

        _write_export(Path("requirements.txt"), runtime_export)
        _write_export(Path("requirements-dev.txt"), dev_export)


def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(description="Portable helpers for Makefile targets.")
    subparsers = parser.add_subparsers(dest="command", required=True)

    help_parser = subparsers.add_parser("help", help="Render Makefile help.")
    help_parser.add_argument("makefiles", nargs="+")

    uv_sync_parser = subparsers.add_parser("uv-sync", help="Run uv sync with VIRTUAL_ENV set.")
    uv_sync_parser.add_argument("--uv", required=True)
    uv_sync_parser.add_argument("--venv", required=True)

    deps_export_parser = subparsers.add_parser("deps-export", help="Export requirements files from uv.lock.")
    deps_export_parser.add_argument("--uv", required=True)

    return parser


def main(argv: list[str] | None = None) -> int:
    parser = build_parser()
    args = parser.parse_args(argv)

    if args.command == "help":
        render_help(args.makefiles)
    elif args.command == "uv-sync":
        uv_sync(args.uv, args.venv)
    elif args.command == "deps-export":
        deps_export(args.uv)
    else:
        parser.error(f"Unsupported command: {args.command}")

    return 0


if __name__ == "__main__":
    raise SystemExit(main(sys.argv[1:]))
