#!/usr/bin/env python3
"""Generate application icons for Windows (.ico) and macOS (.icns).

This script creates both platform icon formats from a single master PNG so
branding stays visually consistent across installers.

Requirements:
- Pillow (for .ico generation)
- macOS tools `sips` and `iconutil` (for .icns generation)
"""

from __future__ import annotations

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

ICONSET_ENTRIES: list[tuple[str, int]] = [
    ("icon_16x16.png", 16),
    ("icon_16x16@2x.png", 32),
    ("icon_32x32.png", 32),
    ("icon_32x32@2x.png", 64),
    ("icon_128x128.png", 128),
    ("icon_128x128@2x.png", 256),
    ("icon_256x256.png", 256),
    ("icon_256x256@2x.png", 512),
    ("icon_512x512.png", 512),
    ("icon_512x512@2x.png", 1024),
]

ICO_SIZES = [(16, 16), (24, 24), (32, 32), (48, 48), (64, 64), (128, 128), (256, 256)]


def _run(cmd: list[str]) -> None:
    subprocess.run(cmd, check=True)


def _require_tool(name: str) -> None:
    if shutil.which(name):
        return
    raise RuntimeError(
        f"Required tool '{name}' not found in PATH. "
        f"Install it and retry."
    )


def generate_icns(source_png: Path, target_icns: Path) -> None:
    """Generate macOS .icns using iconutil and sips."""
    _require_tool("sips")
    _require_tool("iconutil")

    target_icns.parent.mkdir(parents=True, exist_ok=True)

    with tempfile.TemporaryDirectory(prefix="webdrop_iconset_") as tmp:
        iconset_dir = Path(tmp) / "app.iconset"
        iconset_dir.mkdir(parents=True, exist_ok=True)

        for filename, size in ICONSET_ENTRIES:
            out_file = iconset_dir / filename
            _run(
                [
                    "sips",
                    "-z",
                    str(size),
                    str(size),
                    str(source_png),
                    "--out",
                    str(out_file),
                ]
            )

        _run(["iconutil", "-c", "icns", str(iconset_dir), "-o", str(target_icns)])


def generate_ico(source_png: Path, target_ico: Path) -> None:
    """Generate Windows .ico using Pillow."""
    try:
        from PIL import Image
    except ImportError as exc:
        raise RuntimeError(
            "Pillow is required for .ico generation. "
            "Install it with: pip install Pillow"
        ) from exc

    target_ico.parent.mkdir(parents=True, exist_ok=True)

    with Image.open(source_png) as img:
        rgba = img.convert("RGBA")
        rgba.save(target_ico, format="ICO", sizes=ICO_SIZES)


def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(
        description="Generate .ico and .icns icons from a single PNG source"
    )
    parser.add_argument(
        "--source",
        default="resources/icons/app.png",
        help="Master source PNG (default: resources/icons/app.png)",
    )
    parser.add_argument(
        "--icon-ico",
        default="resources/icons/app.ico",
        help="Target .ico path (default: resources/icons/app.ico)",
    )
    parser.add_argument(
        "--icon-icns",
        default="resources/icons/app.icns",
        help="Target .icns path (default: resources/icons/app.icns)",
    )
    parser.add_argument(
        "--only",
        choices=["all", "ico", "icns"],
        default="all",
        help="Generate all icons or only one format",
    )
    return parser.parse_args()


def main() -> int:
    args = parse_args()

    source = Path(args.source).resolve()
    icon_ico = Path(args.icon_ico).resolve()
    icon_icns = Path(args.icon_icns).resolve()

    if not source.exists():
        print(f"ERROR: Source icon not found: {source}")
        return 1

    try:
        if args.only in {"all", "ico"}:
            generate_ico(source, icon_ico)
            print(f"OK: Generated ICO: {icon_ico}")

        if args.only in {"all", "icns"}:
            generate_icns(source, icon_icns)
            print(f"OK: Generated ICNS: {icon_icns}")

        return 0
    except (subprocess.CalledProcessError, RuntimeError) as exc:
        print(f"ERROR: {exc}")
        return 1


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