#!/usr/bin/env python3
"""
从 Unity Assets/Texture 导入 PNG 到 Cocos assets/resources/textures/

用法:
  python3 tools/import_unity_textures.py \\
    --unity-root "/path/to/主站" \\
    [--themes silu,snow,default]
"""
from __future__ import annotations

import argparse
import json
import shutil
import uuid
from pathlib import Path

# 与 GameController UIStyleNames 对应（Unity 目录名 → Cocos 子目录）
THEME_MAP = {
    "default": ".",  # Assets/Texture 根目录单层 png
    "silu": "silu",
    "chinese": "Chinese",
    "redArmy": "redarmy",
    "numMan": "numMan",
    "snow": "snow",
    "sanxing": "sanxing",
}

# 角色 + 砖块核心文件名（各主题有则拷贝，无则跳过）
CORE_NAMES = {
    "Baseblock.png",
    "JumpBlock.png",
    "WallBlock.png",
    "player_F.png",
    "player_B.png",
    "ship_F.png",
    "ship_B.png",
    "Ship_F.png",
    "Prop.png",
    "nProp.png",
    "kuai11.png",
    "素材切图-23.png",
    "素材切图2-23.png",
    "Prop_kuai1.png",
    "Prop_kuai2.png",
    "Prop_kuai.png",
    "nProp_kuai1.png",
    "nProp_kuai2.png",
    "nProp_kuai.png",
    "Prop_Dumpling.png",
    "Prop_Mooncake.png",
    "Prop_Ricedumpling.png",
    "Prop_Zhongzi.png",
    "Prop_star.png",
    "nProp_star.png",
    "nProp_Dumpling.png",
    "nProp_Mooncake.png",
    "nProp_Ricedumpling.png",
    "nProp_Zhongzi.png",
}


# 丝路：对齐 sanxing/snow 命名（skin/待机正面、*Ship_F、Prop_kuai1）
SILU_CANONICAL_COPIES: list[tuple[str, str]] = [
    ("ship_F.png", "siluShip_F.png"),
    ("ship_B.png", "siluShip_B.png"),
    ("Prop.png", "Prop_kuai1.png"),
    ("nProp.png", "nProp_kuai1.png"),
]


def ensure_directory_meta(meta_path: Path) -> None:
    if meta_path.is_file():
        return
    meta_path.write_text(
        json.dumps(
            {
                "ver": "1.2.0",
                "importer": "directory",
                "imported": True,
                "uuid": str(uuid.uuid4()),
                "files": [],
                "subMetas": {},
                "userData": {},
            },
            indent=2,
        ),
        encoding="utf-8",
    )


def ensure_image_meta(meta_path: Path, display_name: str) -> None:
    if meta_path.is_file():
        return
    base_uuid = str(uuid.uuid4())
    meta_path.write_text(
        json.dumps(
            {
                "ver": "1.0.27",
                "importer": "image",
                "imported": False,
                "uuid": base_uuid,
                "files": [".json", ".png"],
                "subMetas": {
                    "6c48a": {
                        "importer": "texture",
                        "uuid": f"{base_uuid}@6c48a",
                        "displayName": display_name,
                        "id": "6c48a",
                        "name": "texture",
                        "userData": {
                            "imageUuidOrDatabaseUri": base_uuid,
                            "isUuid": True,
                            "visible": False,
                        },
                        "ver": "1.0.22",
                        "imported": False,
                        "files": [".json"],
                        "subMetas": {},
                    }
                },
                "userData": {"type": "texture", "redirect": f"{base_uuid}@6c48a"},
            },
            indent=2,
        ),
        encoding="utf-8",
    )


def ensure_png_meta(png_path: Path) -> None:
    ensure_image_meta(png_path.with_suffix(".png.meta"), png_path.stem)


def first_existing_file(*candidates: Path) -> Path | None:
    for path in candidates:
        if path.is_file():
            return path
    return None


def copy_skin_tree(src_skin: Path, dst_skin: Path) -> None:
    """将 player/skin 整树复制到主题根 skin（对齐 sanxing 目录结构）。"""
    if not src_skin.is_dir():
        return
    dst_skin.mkdir(parents=True, exist_ok=True)
    ensure_directory_meta(dst_skin.parent / f"{dst_skin.name}.meta")
    for src in sorted(src_skin.rglob("*")):
        rel = src.relative_to(src_skin)
        dst = dst_skin / rel
        if src.is_dir():
            dst.mkdir(parents=True, exist_ok=True)
            ensure_directory_meta(dst.parent / f"{dst.name}.meta")
            continue
        if src.suffix.lower() != ".png":
            continue
        dst.parent.mkdir(parents=True, exist_ok=True)
        shutil.copy2(src, dst)
        ensure_png_meta(dst)


def normalize_silu_assets(theme_dir: Path) -> None:
    """拷贝丝路实体贴图为标准文件名（保留 Unity 原名，额外写规范别名）。"""
    skin_root = theme_dir / "skin"
    player_skin = theme_dir / "player" / "skin"
    if player_skin.is_dir():
        copy_skin_tree(player_skin, skin_root)

    skin_front = skin_root / "待机正面"
    skin_back = skin_root / "待机背面"
    skin_front.mkdir(parents=True, exist_ok=True)
    skin_back.mkdir(parents=True, exist_ok=True)
    ensure_directory_meta(skin_root.parent / f"{skin_root.name}.meta")
    ensure_directory_meta(skin_front.parent / f"{skin_front.name}.meta")
    ensure_directory_meta(skin_back.parent / f"{skin_back.name}.meta")

    front_src = first_existing_file(
        skin_front / "1.png",
        player_skin / "待机正面" / "1.png",
        theme_dir / "player" / "idel-正" / "1.png",
        theme_dir / "player_F.png",
    )
    if front_src and front_src != skin_front / "1.png":
        shutil.copy2(front_src, skin_front / "1.png")
    if (skin_front / "1.png").is_file():
        ensure_png_meta(skin_front / "1.png")

    back_src = first_existing_file(
        skin_back / "1.png",
        player_skin / "待机背面" / "1.png",
        theme_dir / "player" / "idel-反" / "1.png",
        theme_dir / "player_B.png",
    )
    if back_src and back_src != skin_back / "1.png":
        shutil.copy2(back_src, skin_back / "1.png")
    if (skin_back / "1.png").is_file():
        ensure_png_meta(skin_back / "1.png")

    for src_name, dst_name in SILU_CANONICAL_COPIES:
        src = theme_dir / src_name
        dst = theme_dir / dst_name
        if src.is_file():
            shutil.copy2(src, dst)
            ensure_png_meta(dst)


def normalize_nprop_filenames(theme_dir: Path) -> None:
    """Unity numMan 等主题 nProp 文件名可能带尾空格，统一为无空格文件名。"""
    for png in theme_dir.rglob("nProp*.png"):
        stem = png.stem
        if stem != stem.rstrip():
            fixed = png.with_name(f"{stem.rstrip()}.png")
            if fixed != png:
                if fixed.is_file():
                    png.unlink()
                else:
                    png.rename(fixed)
                meta = png.with_suffix(".png.meta")
                fixed_meta = fixed.with_suffix(".png.meta")
                if meta.is_file() and not fixed_meta.is_file():
                    meta.rename(fixed_meta)


# HUD 按钮（UIMain 右侧，与 themes-database.json hud 字段对应）
HUD_GLOBS = (
    "anniu_*.png",
    "redarmy*.png",
    "素材切图-*.png",
    "素材切图2-*.png",
    "1倍速.png",
    "2倍速.png",
    "4倍速.png",
    "声音.png",
    "声音关闭.png",
    "导航图标.png",
    "重置.png",
    "放大图标.png",
    "缩小图标.png",
)


def copy_hud_assets(unity_tex: Path, out_root: Path, style_key: str, rel: str) -> int:
    """拷贝 Unity UI 按钮贴图（原先 rglob 会跳过 anniu_/倍速/声音）"""
    src = unity_tex if rel == "." else unity_tex / rel
    if not src.is_dir():
        return 0
    dst = out_root / style_key
    dst.mkdir(parents=True, exist_ok=True)
    count = 0
    seen: set[str] = set()
    for pattern in HUD_GLOBS:
        for png in src.glob(pattern):
            if not png.is_file():
                continue
            key = str(png.resolve())
            if key in seen:
                continue
            seen.add(key)
            target = dst / png.name
            shutil.copy2(png, target)
            count += 1
    return count


def copy_theme(unity_tex: Path, out_root: Path, style_key: str, rel: str) -> int:
    src = unity_tex if rel == "." else unity_tex / rel
    dst = out_root / style_key
    dst.mkdir(parents=True, exist_ok=True)
    count = 0

    if rel == ".":
        for png in src.glob("*.png"):
            shutil.copy2(png, dst / png.name)
            if png.name == "Ship_F.png":
                shutil.copy2(png, dst / "ship_F.png")
            count += 1
        return count

    if not src.is_dir():
        print(f"  skip missing theme dir: {src}")
        return 0

    for png in src.rglob("*.png"):
        rel_path = png.relative_to(src)
        # 跳过 HUD 专用碎图（由 copy_hud_assets 扁平拷贝到主题根目录）
        if png.name.startswith("anniu_") or "倍速" in png.name or png.name.startswith("声音"):
            continue
        if png.name.startswith("素材切图") or png.name.startswith("redarmy"):
            continue
        target = dst / rel_path
        target.parent.mkdir(parents=True, exist_ok=True)
        shutil.copy2(png, target)
        count += 1

    # silu 装饰砖块别名（烘焙脚本用 Decor23）
    decor = dst / "素材切图-23.png"
    if decor.is_file():
        shutil.copy2(decor, dst / "Decor23.png")

    normalize_nprop_filenames(dst)
    if style_key == "silu":
        normalize_silu_assets(dst)

    return count


def copy_prop(unity_tex: Path, out_root: Path) -> int:
    src = unity_tex / "Prop"
    if not src.is_dir():
        return 0
    dst = out_root / "prop"
    dst.mkdir(parents=True, exist_ok=True)
    n = 0
    for png in src.glob("*.png"):
        name = png.name.replace("载具 正面", "vehicle_F").replace("载具 背面", "vehicle_B")
        shutil.copy2(png, dst / name)
        n += 1
    return n


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--unity-root", required=True)
    ap.add_argument("--out", default="assets/resources/textures")
    ap.add_argument("--themes", default=",".join(THEME_MAP.keys()))
    args = ap.parse_args()

    project = Path(__file__).resolve().parent.parent
    unity_tex = Path(args.unity_root) / "Assets" / "Texture"
    out_root = project / args.out

    if not unity_tex.is_dir():
        raise SystemExit(f"Unity Texture 不存在: {unity_tex}")

    themes = [t.strip() for t in args.themes.split(",") if t.strip()]
    total = 0
    for key in themes:
        rel = THEME_MAP.get(key)
        if rel is None:
            print(f"unknown theme: {key}")
            continue
        n = copy_theme(unity_tex, out_root, key, rel)
        hn = copy_hud_assets(unity_tex, out_root, key, rel)
        print(f"  {key}: {n} png (+ {hn} hud)")
        total += n + hn

    pn = copy_prop(unity_tex, out_root)
    print(f"  prop: {pn} png")
    total += pn

    print(f"Imported {total} files -> {out_root}")
    print("请在 Cocos Creator 中刷新 assets/resources/textures，然后运行:")
    print("  python3 tools/fix_tile_texture_metas.py")


if __name__ == "__main__":
    main()
