"""render_icon.py: unicode 字形 → 透明背景 PNG。

MSO_SHAPE 覆盖不到的图标 (齿轮、放大镜、文件夹等),用字形渲染兜底。
首选 MSO_SHAPE,见 references/icons.md。

用法:
    python render_icon.py "✓"  --color "#38B2AC" --size 96 -o check.png
    python render_icon.py "★"  --color "#FFC000" --size 128 -o star.png
    python render_icon.py "→"  --color "#1F4E79" --size 64  -o arrow.png

退出码:
  0 = 成功
  1 = Pillow 缺失
  2 = 字体找不到
"""
from __future__ import annotations

import argparse
import sys
from pathlib import Path


def find_font(preferred: list[str]) -> str | None:
    """按顺序找系统字体。返回字体路径或 None。"""
    candidates = []
    # Windows
    candidates += [
        rf"C:\Windows\Fonts\{name}" for name in [
            "seguisym.ttf",       # Segoe UI Symbol
            "seguiemj.ttf",       # Segoe UI Emoji (彩色,慎用)
            "msyh.ttc", "msyh.ttf",  # 微软雅黑
            "simsun.ttc",         # 宋体
            "arial.ttf",
        ]
    ]
    # macOS
    candidates += [
        "/System/Library/Fonts/Apple Symbols.ttf",
        "/System/Library/Fonts/PingFang.ttc",
        "/Library/Fonts/Arial Unicode.ttf",
    ]
    # Linux
    candidates += [
        "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
        "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc",
        "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc",
    ]

    if preferred:
        candidates = preferred + candidates

    for c in candidates:
        if Path(c).exists():
            return c
    return None


def hex_to_rgba(hex_str: str) -> tuple[int, int, int, int]:
    h = hex_str.lstrip("#")
    if len(h) == 6:
        return int(h[0:2], 16), int(h[2:4], 16), int(h[4:6], 16), 255
    if len(h) == 8:
        return int(h[0:2], 16), int(h[2:4], 16), int(h[4:6], 16), int(h[6:8], 16)
    raise ValueError(f"bad hex color: {hex_str}")


def render(glyph: str, color: str, size_px: int, output: Path,
           font_path: str | None, padding: int) -> None:
    try:
        from PIL import Image, ImageDraw, ImageFont
    except ImportError:
        print("[fatal] pip install Pillow", file=sys.stderr)
        sys.exit(1)

    font_path = font_path or find_font([])
    if not font_path:
        print("[fatal] no symbol font found; pass --font /path/to/font.ttf",
              file=sys.stderr)
        sys.exit(2)

    rgba = hex_to_rgba(color)

    # 字体载入,用 size_px 的 0.85 做实际字号让字形不顶格
    font_size = int(size_px * 0.85)
    font = ImageFont.truetype(font_path, font_size)

    # 测量字形真实包围盒
    tmp = Image.new("RGBA", (size_px * 2, size_px * 2), (0, 0, 0, 0))
    draw = ImageDraw.Draw(tmp)
    bbox = draw.textbbox((0, 0), glyph, font=font)
    tw = bbox[2] - bbox[0]
    th = bbox[3] - bbox[1]

    # 输出画布:正方形,边长 = size_px,加 padding
    canvas_size = size_px + 2 * padding
    img = Image.new("RGBA", (canvas_size, canvas_size), (0, 0, 0, 0))
    draw = ImageDraw.Draw(img)

    # 居中绘制 (考虑 bbox 偏移)
    x = (canvas_size - tw) // 2 - bbox[0]
    y = (canvas_size - th) // 2 - bbox[1]
    draw.text((x, y), glyph, font=font, fill=rgba)

    output.parent.mkdir(parents=True, exist_ok=True)
    img.save(output, "PNG")


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("glyph", help="unicode 字符,如 ✓ ★ →")
    ap.add_argument("--color", default="#1F4E79", help="hex,默认 #1F4E79")
    ap.add_argument("--size", type=int, default=96,
                    help="像素边长 (字形主体),默认 96")
    ap.add_argument("--padding", type=int, default=8,
                    help="周围透明边距像素,默认 8")
    ap.add_argument("--font", default=None,
                    help="自定义字体路径 (.ttf/.ttc/.otf)")
    ap.add_argument("-o", "--output", type=Path, required=True,
                    help="输出 PNG 路径")
    args = ap.parse_args()

    render(args.glyph, args.color, args.size, args.output,
           args.font, args.padding)
    size_kb = args.output.stat().st_size / 1024
    print(f"[ok] {args.output}  ({size_kb:.1f} KB)")


if __name__ == "__main__":
    main()
