# pip install pillow
"""
yjm_img_to_360_fix.py

목적:
- 큰 이미지를 360x360 규격으로 자동 변환
- PNG 썸네일 문제를 줄이기 위해 RGBA truecolor PNG로 저장
- yjm_png_rgba_fix.py 와 비슷한 방식의 UI(폴더 선택 / 파일 선택) 제공
- ZIP 기능 없음

지원 형식:
- PNG / JPG / JPEG / WEBP

기능:
1) 파일 또는 폴더 드래그앤드롭 가능
2) 인자가 없으면 UI로 폴더/파일 선택
3) 투명 PNG는 투명 유지
4) PNG의 P모드/팔레트/투명도 문제를 RGBA로 보정
5) 투명 여백 자동 크롭
6) 비율 유지
7) 360x360 중앙 정렬
8) 기본 저장 위치: 원본 폴더 아래 "_360x360_fixed"
9) --overwrite 옵션 사용 시 원본 덮어쓰기 가능

사용 예:
    python yjm_img_to_360_fix.py "C:\\img_folder"
    python yjm_img_to_360_fix.py "C:\\img\\sample.png"
    python yjm_img_to_360_fix.py --overwrite "C:\\img_folder"
"""

import sys
from pathlib import Path
from PIL import Image
import tkinter as tk
from tkinter import filedialog, messagebox

SUPPORTED = {".png", ".jpg", ".jpeg", ".webp"}


def normalize_drop_path(p: str) -> str:
    p = p.strip().strip('"').strip("'")
    if p.startswith("{") and p.endswith("}"):
        p = p[1:-1]
    return p


def gather_images(paths):
    files = []
    seen = set()

    for raw in paths:
        raw = normalize_drop_path(str(raw))
        if not raw:
            continue

        p = Path(raw)
        if not p.exists():
            print(f"[경고] 경로 없음: {p}")
            continue

        if p.is_file() and p.suffix.lower() in SUPPORTED:
            rp = p.resolve()
            if rp not in seen:
                files.append(rp)
                seen.add(rp)

        elif p.is_dir():
            for f in p.rglob("*"):
                if f.is_file() and f.suffix.lower() in SUPPORTED:
                    rp = f.resolve()
                    if rp not in seen:
                        files.append(rp)
                        seen.add(rp)

    return sorted(files)


def has_alpha(im: Image.Image) -> bool:
    return "A" in im.getbands() or im.mode in ("RGBA", "LA", "PA")


def crop_transparent_bbox(im: Image.Image) -> Image.Image:
    if im.mode != "RGBA":
        im = im.convert("RGBA")
    alpha = im.getchannel("A")
    bbox = alpha.getbbox()
    if bbox:
        return im.crop(bbox)
    return im


def make_360_fixed_image(src: Path, overwrite: bool = False, canvas_size: int = 360, padding: int = 4):
    with Image.open(src) as im:
        original_mode = im.mode
        original_size = im.size
        alpha_exists = has_alpha(im)

        # RGBA로 통일 → PNG 팔레트(P) 문제 보정
        rgba = im.convert("RGBA")

        # 투명 배경인 경우 여백 자동 크롭
        if alpha_exists:
            rgba = crop_transparent_bbox(rgba)

        avail = canvas_size - (padding * 2)
        scale = min(avail / rgba.width, avail / rgba.height)

        new_w = max(1, int(round(rgba.width * scale)))
        new_h = max(1, int(round(rgba.height * scale)))
        resized = rgba.resize((new_w, new_h), Image.Resampling.LANCZOS)

        # 원본에 알파가 있으면 투명 배경, 아니면 흰 배경
        if alpha_exists:
            canvas = Image.new("RGBA", (canvas_size, canvas_size), (0, 0, 0, 0))
        else:
            canvas = Image.new("RGBA", (canvas_size, canvas_size), (255, 255, 255, 255))

        x = (canvas_size - new_w) // 2
        y = (canvas_size - new_h) // 2
        canvas.alpha_composite(resized, (x, y))

        if overwrite:
            dst = src.with_suffix(".png")
        else:
            out_dir = src.parent / "_360x360_fixed"
            out_dir.mkdir(parents=True, exist_ok=True)
            dst = out_dir / f"{src.stem}.png"

        # RGBA truecolor PNG로 저장
        canvas.save(dst, format="PNG", optimize=True)

        return {
            "ok": True,
            "src": str(src),
            "dst": str(dst),
            "mode_before": original_mode,
            "size_before": original_size,
            "size_after": canvas.size,
            "alpha": alpha_exists,
        }


def ask_paths():
    root = tk.Tk()
    root.withdraw()

    answer = messagebox.askyesno(
        "360x360 변환 + RGBA Fix",
        "폴더 전체를 처리할까요?\n\n예 = 폴더 선택\n아니오 = 이미지 파일 여러 개 선택"
    )

    if answer:
        folder = filedialog.askdirectory(title="이미지 폴더 선택")
        root.destroy()
        return [folder] if folder else []
    else:
        files = filedialog.askopenfilenames(
            title="이미지 파일 선택",
            filetypes=[
                ("Image files", "*.png;*.jpg;*.jpeg;*.webp"),
                ("PNG", "*.png"),
                ("JPG", "*.jpg;*.jpeg"),
                ("WEBP", "*.webp"),
            ]
        )
        root.destroy()
        return list(files)


def main():
    overwrite = False
    raw_args = []

    for a in sys.argv[1:]:
        if a == "--overwrite":
            overwrite = True
        else:
            raw_args.append(a)

    if not raw_args:
        raw_args = ask_paths()

    files = gather_images(raw_args)

    if not files:
        print("처리할 이미지가 없습니다.")
        try:
            root = tk.Tk()
            root.withdraw()
            messagebox.showwarning("360x360 변환 + RGBA Fix", "처리할 이미지가 없습니다.")
            root.destroy()
        except Exception:
            pass
        return

    print(f"총 {len(files)}개 이미지 처리 시작")
    print(f"저장 방식: {'원본 덮어쓰기' if overwrite else '_360x360_fixed 폴더에 저장'}")
    print("-" * 80)

    ok_count = 0
    fail_count = 0
    alpha_count = 0
    palette_like_count = 0

    for src in files:
        try:
            with Image.open(src) as test_im:
                before_mode = test_im.mode
            result = make_360_fixed_image(src, overwrite=overwrite)

            ok_count += 1
            if result["alpha"]:
                alpha_count += 1
            if before_mode in ("P", "PA"):
                palette_like_count += 1

            print(
                f"[완료] {Path(result['src']).name} | "
                f"{result['mode_before']} {result['size_before'][0]}x{result['size_before'][1]} "
                f"-> PNG RGBA {result['size_after'][0]}x{result['size_after'][1]}"
            )

        except Exception as e:
            fail_count += 1
            print(f"[실패] {Path(src).name} | {e}")

    print("-" * 80)
    print(f"완료: {ok_count}개, 실패: {fail_count}개")
    print(f"투명(alpha) 유지 처리: {alpha_count}개")
    print(f"팔레트(P/PA) 계열 RGBA 보정: {palette_like_count}개")

    try:
        root = tk.Tk()
        root.withdraw()
        messagebox.showinfo(
            "360x360 변환 + RGBA Fix 완료",
            f"완료: {ok_count}개\n"
            f"실패: {fail_count}개\n"
            f"투명(alpha) 유지 처리: {alpha_count}개\n"
            f"팔레트(P/PA) RGBA 보정: {palette_like_count}개\n\n"
            f"{'원본 덮어쓰기 완료' if overwrite else '_360x360_fixed 폴더에 저장 완료'}"
        )
        root.destroy()
    except Exception:
        pass


if __name__ == "__main__":
    main()
