#!/usr/bin/env python3
from __future__ import annotations

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


ROOT = Path(__file__).resolve().parents[1]
TUI_ENTRY = ROOT / "jiuwenswarm" / "channels" / "tui" / "frontend" / "src" / "index.ts"
OUTPUT_ROOT = ROOT / "packages" / "jiuwenswarm-tui" / "jiuwenswarm_tui" / "resources" / "tui-bin"

TARGETS = {
    "linux-x64": "bun-linux-x64",
    "linux-arm64": "bun-linux-arm64",
    "macos-x64": "bun-darwin-x64",
    "macos-arm64": "bun-darwin-arm64",
    "windows-x64": "bun-windows-x64",
    #"windows-arm64": "bun-windows-arm64",
}


def current_platform_key() -> str:
    import platform

    system = platform.system().lower()
    machine = platform.machine().lower()
    machine = {"x86_64": "x64", "amd64": "x64", "aarch64": "arm64"}.get(machine, machine)
    if system == "linux":
        return f"linux-{machine}"
    if system == "darwin":
        return f"macos-{machine}"
    if system == "windows":
        return f"windows-{machine}"
    raise SystemExit(f"unsupported platform for current target: {system}-{machine}")


def output_binary_name(platform_key: str) -> str:
    return "jiuwenswarm-tui.exe" if platform_key.startswith("windows-") else "jiuwenswarm-tui"


def resolve_requested_targets(raw: str) -> list[str]:
    if raw == "all":
        return list(TARGETS.keys())
    if raw == "current":
        return [current_platform_key()]
    values = [part.strip() for part in raw.split(",") if part.strip()]
    unknown = [value for value in values if value not in TARGETS]
    if unknown:
        valid = ", ".join(["current", "all", *TARGETS.keys()])
        raise SystemExit(f"unknown target(s): {', '.join(unknown)}; valid: {valid}")
    return values


def _fix_macos_signature(binary: Path) -> None:
    """Fix Bun's broken ad-hoc code signature on macOS.

    Bun --compile produces a Mach-O with an invalid LC_CODE_SIGNATURE segment,
    which causes macOS to kill the binary at launch and prevents codesign/ldid
    from working directly.  Stripping the bad signature first, then applying a
    fresh ad-hoc signature resolves this.
    """
    if os.name != "nt" and shutil.which("codesign") is not None:
        subprocess.run(["codesign", "--remove-signature", str(binary)], check=False)
        subprocess.run(["codesign", "-s", "-", str(binary)], check=True)


def build_target(platform_key: str) -> Path:
    bun_target = TARGETS[platform_key]
    output_dir = OUTPUT_ROOT / platform_key
    output_dir.mkdir(parents=True, exist_ok=True)
    output_path = output_dir / output_binary_name(platform_key)
    if output_path.exists():
        output_path.unlink()

    cmd = [
        "bun",
        "build",
        "--compile",
        "--minify",
        "--target",
        bun_target,
        "--outfile",
        str(output_path),
        str(TUI_ENTRY),
    ]
    subprocess.run(cmd, cwd=ROOT, check=True)

    if platform_key.startswith("macos-"):
        _fix_macos_signature(output_path)

    return output_path


def main() -> None:
    parser = argparse.ArgumentParser(description="Build jiuwenswarm-tui native binaries with Bun.")
    parser.add_argument(
        "--target",
        default="current",
        help="Build target: current, all, or comma-separated platform keys",
    )
    parser.add_argument(
        "--clean",
        action="store_true",
        help="Remove existing packaged tui binaries before building",
    )
    args = parser.parse_args()

    if shutil.which("bun") is None:
        raise SystemExit("bun is required to build jiuwenswarm-tui binaries")
    if not TUI_ENTRY.exists():
        raise SystemExit(f"CLI entry not found: {TUI_ENTRY}")

    if args.clean and OUTPUT_ROOT.exists():
        shutil.rmtree(OUTPUT_ROOT)

    targets = resolve_requested_targets(args.target)
    built: list[Path] = []
    for target in targets:
        built.append(build_target(target))

    for path in built:
        print(path.relative_to(ROOT))


if __name__ == "__main__":
    try:
        main()
    except subprocess.CalledProcessError as exc:
        raise SystemExit(exc.returncode) from exc