#!/usr/bin/env python3
"""
烘焙「地图模块」预制体（对齐 Unity Tile Palette 中的单个 Tile）。

输出: assets/resources/map-tiles/MapTile_*.prefab
在关卡编辑器右侧面板中作为笔刷模块使用。
"""
from __future__ import annotations

import json
import random
import string
import uuid
from pathlib import Path

LAYER_DEFAULT = 1073741824

CELL = 56
TILE_SIZE = CELL * 0.9

# 与 Unity SILU 调色板一致
MAP_TILES = [
    {
        "name": "MapTile_Baseblock",
        "display": "地面 Baseblock",
        "layer": "ground",
        "tileKey": "Baseblock",
        "texture": "textures/silu/Baseblock",
        "spriteUuid": "5625da25-9915-416f-be60-c6decb355672@f9941",
        "alpha": 255,
    },
    {
        "name": "MapTile_JumpBlock",
        "display": "跳跃 JumpBlock",
        "layer": "ground",
        "tileKey": "JumpBlock",
        "texture": "textures/silu/JumpBlock",
        "spriteUuid": None,
        "alpha": 255,
    },
    {
        "name": "MapTile_WallBlock",
        "display": "墙 WallBlock",
        "layer": "border",
        "tileKey": "WallBlock",
        "texture": "textures/silu/WallBlock",
        "spriteUuid": None,
        "alpha": 255,
    },
    {
        "name": "MapTile_Decor23",
        "display": "装饰 素材23",
        "layer": "border",
        "tileKey": "Decor23",
        "texture": "textures/silu/Decor23",
        "spriteUuid": None,
        "alpha": 255,
    },
]


def uid() -> str:
    return str(uuid.uuid4())


def vec3(x: float, y: float, z: float = 0) -> dict:
    return {"__type__": "cc.Vec3", "x": x, "y": y, "z": z}


def quat() -> dict:
    return {"__type__": "cc.Quat", "x": 0, "y": 0, "z": 0, "w": 1}


def file_id() -> str:
    chars = string.ascii_letters + string.digits
    return "".join(random.choices(chars, k=22))


def read_sprite_uuid_from_meta(project: Path, texture_path: str) -> str | None:
    meta_path = project / "assets/resources" / f"{texture_path}.png.meta"
    if not meta_path.is_file():
        return None
    try:
        meta = json.loads(meta_path.read_text(encoding="utf-8"))
        base = meta.get("uuid")
        if base:
            return f"{base}@f9941"
    except Exception:
        pass
    return None


def build_tile_prefab(tile: dict) -> list:
    objs: list[dict] = []
    root_id = 1

    objs.append(
        {
            "__type__": "cc.Prefab",
            "_name": tile["name"],
            "_objFlags": 0,
            "_native": "",
            "data": {"__id__": root_id},
            "optimizationPolicy": 0,
            "persistent": False,
        }
    )
    objs.append(
        {
            "__type__": "cc.Node",
            "_name": tile["name"],
            "_objFlags": 0,
            "_parent": None,
            "_children": [],
            "_active": True,
            "_components": [],
            "_prefab": {"__id__": 2},
            "_lpos": vec3(0, 0, 0),
            "_lrot": quat(),
            "_lscale": vec3(1, 1, 1),
            "_layer": LAYER_DEFAULT,
            "_euler": vec3(0, 0, 0),
            "_id": "",
        }
    )
    objs.append(
        {
            "__type__": "cc.PrefabInfo",
            "root": {"__id__": root_id},
            "asset": {"__id__": 0},
            "fileId": file_id(),
        }
    )
    return objs


def write_meta(prefab_path: Path, prefab_uuid: str) -> None:
    meta = {
        "ver": "1.1.50",
        "importer": "prefab",
        "imported": True,
        "uuid": prefab_uuid,
        "files": [".json"],
        "subMetas": {},
        "userData": {"syncNodeName": prefab_path.stem},
    }
    prefab_path.with_suffix(".prefab.meta").write_text(
        json.dumps(meta, indent=2), encoding="utf-8"
    )


def main():
    project = Path(__file__).resolve().parent.parent
    out = project / "assets/resources/map-tiles"
    out.mkdir(parents=True, exist_ok=True)

    catalog = []
    for tile in MAP_TILES:
        sprite_uuid = tile.get("spriteUuid") or read_sprite_uuid_from_meta(
            project, tile["texture"]
        )
        if not sprite_uuid:
            sprite_uuid = "5625da25-9915-416f-be60-c6decb355672@f9941"
            print(f"  warn: {tile['name']} 使用 Baseblock 占位，请在编辑器导入 {tile['texture']}.png 后重烘焙")

        p = out / f"{tile['name']}.prefab"
        p.write_text(json.dumps(build_tile_prefab(tile), indent=2), encoding="utf-8")
        write_meta(p, uid())
        catalog.append(
            {
                "name": tile["name"],
                "display": tile["display"],
                "layer": tile["layer"],
                "tileKey": tile["tileKey"],
                "texture": tile["texture"],
                "prefab": f"map-tiles/{tile['name']}",
            }
        )
        print(f"  baked {tile['name']}")

    (out / "_palette.json").write_text(
        json.dumps({"tiles": catalog}, indent=2, ensure_ascii=False), encoding="utf-8"
    )
    print(f"Palette catalog -> {out / '_palette.json'}")


if __name__ == "__main__":
    main()
