from __future__ import annotations

import argparse
import shutil
import subprocess
import sys
from pathlib import Path


PROJECT_DIR = Path(__file__).resolve().parent.parent
VENV_DIR = PROJECT_DIR / ".venv"
VENV_PYTHON = VENV_DIR / "Scripts" / "python.exe"
REQUIREMENTS_FILE = PROJECT_DIR / "requirements.txt"


def run(command: list[str], *, cwd: Path | None = None, check: bool = True) -> subprocess.CompletedProcess[str]:
    return subprocess.run(
        command,
        cwd=cwd or PROJECT_DIR,
        check=check,
        text=True,
        capture_output=True,
    )


def create_venv(base_python: str) -> None:
    run([base_python, "-m", "venv", str(VENV_DIR)])


def recreate_venv(base_python: str) -> None:
    if VENV_DIR.exists():
        shutil.rmtree(VENV_DIR)
    create_venv(base_python)


def ensurepip() -> None:
    run([str(VENV_PYTHON), "-m", "ensurepip", "--upgrade"])


def remove_path(path: Path) -> None:
    if not path.exists():
        return
    if path.is_dir():
        shutil.rmtree(path)
    else:
        path.unlink()


def repair_pip_in_place() -> None:
    site_packages = VENV_DIR / "Lib" / "site-packages"
    scripts_dir = VENV_DIR / "Scripts"

    for pattern in ("pip", "pip-*.dist-info", "setuptools", "setuptools-*.dist-info", "wheel", "wheel-*.dist-info"):
        for path in site_packages.glob(pattern):
            remove_path(path)

    for pattern in ("pip*.exe", "pip*.bat"):
        for path in scripts_dir.glob(pattern):
            remove_path(path)


def pip_is_healthy() -> tuple[bool, str]:
    if not VENV_PYTHON.exists():
        return False, "Missing .venv\\Scripts\\python.exe"

    checks = [
        [str(VENV_PYTHON), "-m", "pip", "--version"],
        [
            str(VENV_PYTHON),
            "-c",
            "import pip._internal.resolution.resolvelib.resolver",
        ],
    ]
    for command in checks:
        result = run(command, check=False)
        if result.returncode != 0:
            return False, (result.stderr or result.stdout).strip()
    return True, ""


def install_requirements() -> None:
    run([str(VENV_PYTHON), "-m", "pip", "install", "-r", str(REQUIREMENTS_FILE), "pyinstaller"])


def main() -> int:
    parser = argparse.ArgumentParser(description="Ensure CitiFox ERP .venv exists and pip is healthy.")
    parser.add_argument(
        "--install-requirements",
        action="store_true",
        help="Install requirements.txt and pyinstaller into the project virtualenv.",
    )
    parser.add_argument(
        "--base-python",
        default=sys.executable,
        help="Base Python executable used to create or recreate .venv.",
    )
    args = parser.parse_args()

    if not VENV_PYTHON.exists():
        print("Creating project virtualenv...")
        create_venv(args.base_python)

    print("Checking project virtualenv health...")
    healthy, detail = pip_is_healthy()
    if not healthy:
        print("Detected broken pip/venv. Repairing pip in place...")
        if detail:
            print(detail)
        repair_pip_in_place()
        ensurepip()

    healthy, detail = pip_is_healthy()
    if not healthy:
        print("In-place repair was not enough. Recreating .venv...")
        if detail:
            print(detail)
        recreate_venv(args.base_python)
        ensurepip()

    healthy, detail = pip_is_healthy()
    if not healthy:
        raise RuntimeError(f"Project virtualenv is still unhealthy after repair: {detail}")

    if args.install_requirements:
        print("Installing project requirements...")
        install_requirements()

    print("Project virtualenv is ready.")
    return 0


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