from __future__ import annotations

import argparse
import importlib.util
import shutil
import subprocess
import sys
from pathlib import Path

from set_version import PYPROJECT_PATH, extract_project_version, write_project_version


ROOT = Path(__file__).resolve().parent.parent


def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(description="Build a wheel for the project.")
    parser.add_argument("--version", help="Optionally set the project version before building.")
    parser.add_argument("--outdir", default="dist", help="Directory where the wheel will be written.")
    parser.add_argument("--no-clean", action="store_true", help="Keep existing build and output directories.")
    return parser.parse_args()


def resolve_output_dir(outdir: str) -> Path:
    output_dir = Path(outdir)
    if not output_dir.is_absolute():
        output_dir = ROOT / output_dir
    return output_dir


def ensure_build_dependency() -> None:
    if importlib.util.find_spec("build") is None:
        raise RuntimeError(
            'Missing dependency "build". Install development dependencies with '\
            '"python -m pip install -e .[dev]" or install "build" directly.'
        )


def clean_build_artifacts(output_dir: Path) -> None:
    for path in (ROOT / "build", output_dir):
        if path.exists():
            shutil.rmtree(path)


def build_wheel(output_dir: Path) -> None:
    command = [
        sys.executable,
        "-m",
        "build",
        "--wheel",
        "--outdir",
        str(output_dir),
    ]
    subprocess.run(command, check=True, cwd=ROOT)


def main() -> int:
    args = parse_args()
    output_dir = resolve_output_dir(args.outdir)

    if args.version:
        previous_version, updated_version = write_project_version(PYPROJECT_PATH, args.version)
        if previous_version == updated_version:
            print(f"Version already set to {updated_version}")
        else:
            print(f"Updated version: {previous_version} -> {updated_version}")

    ensure_build_dependency()

    if not args.no_clean:
        clean_build_artifacts(output_dir)
    output_dir.mkdir(parents=True, exist_ok=True)

    version = extract_project_version(PYPROJECT_PATH.read_text(encoding="utf-8"))
    print(f"Building wheel for version {version} into {output_dir}")
    build_wheel(output_dir)

    wheels = sorted(output_dir.glob("*.whl"))
    if not wheels:
        raise RuntimeError("Build completed without producing a wheel file.")
    for wheel in wheels:
        print(f"Built wheel: {wheel}")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())