#!/usr/bin/env python3
"""Flutter 앱 아이콘 원본을 검증하고 Android/iOS 크기로 생성합니다."""

from __future__ import annotations

import argparse
import hashlib
import json
import sys
from pathlib import Path

from PIL import Image, ImageOps

ANDROID_SIZES = {
    "mipmap-mdpi/ic_launcher.png": 48,
    "mipmap-hdpi/ic_launcher.png": 72,
    "mipmap-xhdpi/ic_launcher.png": 96,
    "mipmap-xxhdpi/ic_launcher.png": 144,
    "mipmap-xxxhdpi/ic_launcher.png": 192,
}

IOS_SIZES = {
    "Icon-App-20x20@1x.png": 20,
    "Icon-App-20x20@2x.png": 40,
    "Icon-App-20x20@3x.png": 60,
    "Icon-App-29x29@1x.png": 29,
    "Icon-App-29x29@2x.png": 58,
    "Icon-App-29x29@3x.png": 87,
    "Icon-App-40x40@1x.png": 40,
    "Icon-App-40x40@2x.png": 80,
    "Icon-App-40x40@3x.png": 120,
    "Icon-App-60x60@2x.png": 120,
    "Icon-App-60x60@3x.png": 180,
    "Icon-App-76x76@1x.png": 76,
    "Icon-App-76x76@2x.png": 152,
    "Icon-App-83.5x83.5@2x.png": 167,
    "Icon-App-1024x1024@1x.png": 1024,
}


def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(description="Flutter 앱 아이콘 리소스 생성")
    parser.add_argument("--input", required=True, type=Path, help="1024x1024 이상 PNG/JPG 원본")
    parser.add_argument("--output", required=True, type=Path, help="결과 디렉터리")
    parser.add_argument("--background", default="#FFFFFF", help="투명 영역 배경색")
    return parser.parse_args()


def validate_source(image: Image.Image, source: Path) -> None:
    width, height = image.size
    if width != height:
        raise ValueError(f"아이콘은 정사각형이어야 합니다: {width}x{height}")
    if width < 1024:
        raise ValueError(f"아이콘은 최소 1024x1024여야 합니다: {width}x{height}")
    if source.stat().st_size > 20 * 1024 * 1024:
        raise ValueError("아이콘 파일은 20MB 이하여야 합니다.")


def flatten(image: Image.Image, background: str) -> Image.Image:
    rgba = ImageOps.exif_transpose(image).convert("RGBA")
    canvas = Image.new("RGBA", rgba.size, background)
    canvas.alpha_composite(rgba)
    return canvas.convert("RGB")


def save_sizes(image: Image.Image, root: Path, sizes: dict[str, int]) -> list[dict[str, object]]:
    files: list[dict[str, object]] = []
    for relative, size in sizes.items():
        target = root / relative
        target.parent.mkdir(parents=True, exist_ok=True)
        resized = image.resize((size, size), Image.Resampling.LANCZOS)
        resized.save(target, format="PNG", optimize=True)
        digest = hashlib.sha256(target.read_bytes()).hexdigest()
        files.append({"path": str(relative), "width": size, "height": size, "sha256": digest})
    return files


def main() -> int:
    args = parse_args()
    try:
        with Image.open(args.input) as source:
            validate_source(source, args.input)
            image = flatten(source, args.background)
            output = args.output.resolve()
            android = save_sizes(image, output / "android", ANDROID_SIZES)
            ios = save_sizes(image, output / "ios", IOS_SIZES)
            manifest = {
                "source": str(args.input.resolve()),
                "sourceSize": list(source.size),
                "android": android,
                "ios": ios,
            }
            (output / "asset-manifest.json").write_text(
                json.dumps(manifest, ensure_ascii=False, indent=2), encoding="utf-8"
            )
    except (OSError, ValueError) as exc:
        print(f"오류: {exc}", file=sys.stderr)
        return 1

    print(f"완료: {args.output}")
    return 0


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