#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""poster.py — 把某个设定图目录做成「带编号合辑」：每张图**左上角压编号徽章**，下方小字标注名称。

用法:
  python3 poster.py <目录> [--cols 3] [--out 输出.jpg] [--theme formal|cute] [--cell-w 600] [--no-name]

主题：formal = 深炭底 + 暗金徽章（配正式版电影风）；cute = 米黄宣纸底 + 朱红徽章（配可爱版）
"""
import argparse, os, sys
from PIL import Image, ImageDraw, ImageFont

BOLD = "/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc"
SERIF = "/usr/share/fonts/opentype/source-han-cjk/SourceHanSerifSC-Medium.otf"

THEMES = {
    "formal": dict(bg=(26, 26, 28), cell=(38, 38, 42), badge=(150, 42, 32), badge_edge=(226, 196, 128),
                   num=(255, 246, 226), name=(206, 200, 188), gap=14),
    "cute":   dict(bg=(247, 244, 236), cell=(255, 253, 248), badge=(196, 66, 58), badge_edge=(240, 205, 160),
                   num=(255, 252, 246), name=(96, 88, 78), gap=14),
}


def load_font(path, size):
    try:
        return ImageFont.truetype(path, size)
    except Exception:
        return ImageFont.truetype(BOLD, size)


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("dir")
    ap.add_argument("--cols", type=int, default=3)
    ap.add_argument("--out", default=None)
    ap.add_argument("--theme", default="formal", choices=list(THEMES))
    ap.add_argument("--cell-w", type=int, default=600)
    ap.add_argument("--no-name", action="store_true")
    ap.add_argument("--start", type=int, default=1, help="编号起始")
    a = ap.parse_args()

    T = THEMES[a.theme]
    files = sorted(f for f in os.listdir(a.dir)
                   if f.lower().endswith((".png", ".jpg", ".jpeg")) and not f.startswith("_"))
    if not files:
        sys.exit("目录里没有图片: " + a.dir)
    out = a.out or os.path.join(a.dir, "_合辑.jpg")

    cell_w = a.cell_w
    cell_h = int(cell_w * 4 / 3)                      # 3:4 立绘
    cap_h = 0 if a.no_name else int(cell_w * 0.085)
    cols = a.cols
    rows = (len(files) + cols - 1) // cols
    gap = T["gap"]
    W = cols * cell_w + (cols + 1) * gap
    H = rows * (cell_h + cap_h) + (rows + 1) * gap

    sheet = Image.new("RGB", (W, H), T["bg"])
    d = ImageDraw.Draw(sheet)
    f_num = load_font(BOLD, int(cell_w * 0.075))
    f_name = load_font(BOLD, int(cell_w * 0.040))

    for i, fn in enumerate(files):
        r, c = divmod(i, cols)
        x = gap + c * (cell_w + gap)
        y = gap + r * (cell_h + cap_h + gap)
        # 底板
        d.rounded_rectangle([x - 3, y - 3, x + cell_w + 3, y + cell_h + 3], radius=8, fill=T["cell"])
        try:
            im = Image.open(os.path.join(a.dir, fn)).convert("RGB")
        except Exception as e:
            print("跳过", fn, e); continue
        # 铺满单元格（3:4 直接缩放，其他比例居中裁切）
        tr = cell_w / cell_h
        ir = im.width / im.height
        if ir > tr:
            nw = int(im.height * tr)
            im = im.crop(((im.width - nw) // 2, 0, (im.width + nw) // 2, im.height))
        else:
            nh = int(im.width / tr)
            im = im.crop((0, (im.height - nh) // 2, im.width, (im.height + nh) // 2))
        im = im.resize((cell_w, cell_h), Image.LANCZOS)
        sheet.paste(im, (x, y))

        # 左上角编号徽章
        num = f"{i + a.start:02d}"
        bw, bh = int(cell_w * 0.17), int(cell_w * 0.13)
        bx, by = x + int(cell_w * 0.030), y + int(cell_w * 0.030)
        d.rounded_rectangle([bx, by, bx + bw, by + bh], radius=int(bh * 0.28),
                            fill=T["badge"], outline=T["badge_edge"], width=3)
        tb = d.textbbox((0, 0), num, font=f_num)
        d.text((bx + (bw - (tb[2] - tb[0])) / 2 - tb[0], by + (bh - (tb[3] - tb[1])) / 2 - tb[1]),
               num, font=f_num, fill=T["num"])

        if cap_h:
            name = os.path.splitext(fn)[0]
            name = name.replace("可爱版-", "").replace("正式版-", "")
            tb = d.textbbox((0, 0), name, font=f_name)
            d.text((x + (cell_w - (tb[2] - tb[0])) / 2 - tb[0], y + cell_h + (cap_h - (tb[3] - tb[1])) / 2 - tb[1]),
                   name, font=f_name, fill=T["name"])

    sheet.save(out, quality=90)
    print(f"合辑已写 {out}　{sheet.size}　{len(files)} 张（编号 {a.start:02d}–{a.start + len(files) - 1:02d}）")


if __name__ == "__main__":
    main()
