"""Helpers for building a distributable macOS worker app and installer package."""

from __future__ import annotations

import platform
import plistlib
import shutil
import subprocess
from pathlib import Path
from tempfile import TemporaryDirectory

APP_NAME = "Ambient"
APP_BUNDLE_NAME = f"{APP_NAME}.app"
APP_BUNDLE_ID = "com.ambient.worker"
PKG_NAME = "HiveCompute-Worker.pkg"


def build_info_plist(version: str) -> dict[str, str]:
    """Create the minimal Info.plist for the packaged worker app bundle."""
    return {
        "CFBundleDevelopmentRegion": "en",
        "CFBundleDisplayName": APP_NAME,
        "CFBundleExecutable": APP_NAME,
        "CFBundleIdentifier": APP_BUNDLE_ID,
        "CFBundleInfoDictionaryVersion": "6.0",
        "CFBundleName": APP_NAME,
        "CFBundlePackageType": "APPL",
        "CFBundleShortVersionString": version,
        "CFBundleVersion": version,
        "LSMinimumSystemVersion": "13.0",
    }


def create_app_bundle(output_dir: Path, package_source: Path, version: str) -> Path:
    """Build a self-contained .app bundle using pip install --target for relocatability.

    Args:
        output_dir: Directory to create the .app in
        package_source: Path to the project root (containing pyproject.toml)
        version: Version string for Info.plist
    """
    app_dir = output_dir / APP_BUNDLE_NAME
    contents_dir = app_dir / "Contents"
    macos_dir = contents_dir / "MacOS"
    resources_dir = contents_dir / "Resources"
    lib_dir = resources_dir / "lib"

    if app_dir.exists():
        shutil.rmtree(app_dir)

    macos_dir.mkdir(parents=True, exist_ok=True)
    resources_dir.mkdir(parents=True, exist_ok=True)

    # Install the package and all deps into a self-contained lib directory.
    # This avoids absolute-path shebangs and symlinks from the build venv.
    subprocess.run(
        [
            "pip", "install",
            "--target", str(lib_dir),
            "--no-cache-dir",
            str(package_source) + "[worker]",
        ],
        check=True,
        capture_output=True,
        text=True,
    )

    (contents_dir / "Info.plist").write_bytes(plistlib.dumps(build_info_plist(version)))
    _write_executable(macos_dir / APP_NAME, _app_launcher_script())
    _write_executable(resources_dir / f"{APP_NAME}.command", _onboard_command_script())
    return app_dir


def build_pkgbuild_command(pkg_root: Path, output_pkg: Path, version: str) -> list[str]:
    """Build the pkgbuild command used for packaging the app bundle."""
    return [
        "pkgbuild",
        "--root", str(pkg_root),
        "--identifier", f"{APP_BUNDLE_ID}.pkg",
        "--version", version,
        "--install-location", "/",
        str(output_pkg),
    ]


def build_worker_installer(output_dir: Path, package_source: Path, version: str) -> tuple[Path, Path]:
    """Create both the .app bundle and a flat .pkg installer in the output directory."""
    _ensure_pkgbuild_available()

    output_root = output_dir.expanduser().resolve()
    output_root.mkdir(parents=True, exist_ok=True)
    app_bundle = create_app_bundle(output_root, package_source, version)
    pkg_path = output_root / PKG_NAME
    pkg_path.unlink(missing_ok=True)

    with TemporaryDirectory(prefix="hivecompute-pkg-") as temp_dir:
        pkg_root = Path(temp_dir) / "pkgroot"
        applications_dir = pkg_root / "Applications"
        applications_dir.mkdir(parents=True, exist_ok=True)
        shutil.copytree(app_bundle, applications_dir / app_bundle.name, symlinks=True)
        subprocess.run(
            build_pkgbuild_command(pkg_root, pkg_path, version),
            check=True,
            capture_output=True,
            text=True,
        )

    return app_bundle, pkg_path


def _app_launcher_script() -> str:
    return """#!/bin/zsh
set -euo pipefail
APP_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
open -a Terminal "$APP_ROOT/Resources/Ambient.command"
"""


def _onboard_command_script() -> str:
    """Wrapper that uses system Python3 with the bundled library directory."""
    return """#!/bin/zsh
set -uo pipefail
SCRIPT_ROOT="$(cd "$(dirname "$0")" && pwd)"
LIB_DIR="$SCRIPT_ROOT/lib"
export PYTHONPATH="$LIB_DIR${PYTHONPATH:+:$PYTHONPATH}"
export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH"

python3 -m hive_compute.cli init
status=$?
echo
if [[ $status -eq 0 ]]; then
  echo "Ambient onboarding finished."
else
  echo "Ambient onboarding failed with exit code $status."
fi
read '?Press Return to close...'
exit $status
"""


def _write_executable(path: Path, content: str) -> None:
    path.write_text(content, encoding="utf-8")
    path.chmod(0o755)


def _ensure_pkgbuild_available() -> None:
    if platform.system() != "Darwin" or not shutil.which("pkgbuild"):
        raise RuntimeError("macOS packaging requires pkgbuild on a Mac")
