"""Pre-generate scanvas_S.ico from Design/logo_V2.png for PyInstaller spec.

Called by build.bat before PyInstaller runs. Standalone so encoding issues in
.bat don't break it. Mirrors SCanvasApp._setup_window_icon logic.
"""
from __future__ import annotations

import sys
from pathlib import Path

import numpy as np
from PIL import Image
from scipy import ndimage as nd


def main() -> int:
    root = Path(__file__).resolve().parent
    src = root / "Design" / "logo_V2.png"
    dst_dir = root / "cache" / "icons"
    dst_dir.mkdir(parents=True, exist_ok=True)
    ico = dst_dir / "scanvas_S.ico"

    if not src.exists():
        print(f"[icon] source not found: {src}")
        return 1

    pil = Image.open(src).convert("RGBA")
    arr = np.asarray(pil).copy()
    v = np.maximum.reduce([arr[..., 0], arr[..., 1], arr[..., 2]])
    arr[..., 3] = np.where(v < 90, 0, arr[..., 3])

    # Crop left ~32% to isolate the 'S' letter
    crop_w = min(arr.shape[1], 850)
    carr = arr[:, :crop_w, :]
    mask = carr[..., 3] > 100
    labeled, ncomp = nd.label(mask)
    if ncomp == 0:
        print("[icon] no foreground content found")
        return 1
    sizes = nd.sum(mask, labeled, range(1, ncomp + 1))
    max_size = float(sizes.max())
    keep = [i + 1 for i, s in enumerate(sizes) if s >= max_size * 0.1]
    keep_mask = np.isin(labeled, keep)
    cc = carr.copy()
    cc[..., 3] = np.where(keep_mask, carr[..., 3], 0)

    ys, xs = np.where(keep_mask)
    cropped = Image.fromarray(
        cc[int(ys.min()):int(ys.max()) + 1, int(xs.min()):int(xs.max()) + 1, :],
        "RGBA",
    )
    cw, ch = cropped.size
    side = max(cw, ch)
    pad = max(int(side * 0.04), 4)
    sp = side + 2 * pad
    sq = Image.new("RGBA", (sp, sp), (0, 0, 0, 0))
    sq.paste(cropped, ((sp - cw) // 2, (sp - ch) // 2), cropped)
    sq.save(
        ico, format="ICO",
        sizes=[(16, 16), (32, 32), (48, 48), (64, 64), (128, 128), (256, 256)],
    )
    print(f"[icon] {ico} ({ico.stat().st_size} bytes)")
    return 0


if __name__ == "__main__":
    sys.exit(main())
