#!/usr/bin/env python3
"""
Generate Godot 4 .tscn modular kit scenes using CSG nodes.
All dimensions in Godot meters, grid base = 2.56m (256cm).
"""

import os

SCENES_DIR = os.path.expanduser("/home/oplabs/tactical-shooter/client/assets/scenes/modular")
MAT_BASE = "res://assets/materials"

# Grid constants
U = 2.56       # 1 modular unit (256cm)
W = 0.16       # wall thickness (16cm)
F = 0.08       # floor thickness (8cm)

# Material name shortcuts
MAT_WALL = "wall_concrete_01"
MAT_WALL2 = "wall_concrete_02"
MAT_FLOOR = "floor_concrete_01"
MAT_FLOOR_TILE = "floor_tile_01"
MAT_METAL = "metal_structural_01"
MAT_BLUE = "accent_team_blue"
MAT_RED = "accent_team_red"


def tsnode(name, type_name, parent=".", props=None):
    """Build a [node] entry for .tscn format."""
    lines = [f'[node name="{name}" type="{type_name}" parent="{parent}"]']
    if props:
        for k, v in props.items():
            lines.append(f"{k} = {v}")
    return "\n".join(lines)


# ── Wall pieces ──────────────────────────────────────────────────────────

def build_wall_straight():
    """Straight wall — 2.56m x 2.56m x 0.16m."""
    lines = [
        '[gd_scene load_steps=2 format=3]',
        f'[ext_resource type="Material" path="{MAT_BASE}/{MAT_WALL}.tres" id="1"]',
        '',
        tsnode("WallStraight01", "CSGBox3D", ".", {
            "size": f"Vector3({U}, {U}, {W})",
            "material": 'ExtResource("1")',
            "use_collision": "true",
        }),
    ]
    return "\n".join(lines) + "\n"


def build_wall_corner():
    """L-corner — two CSG boxes in a CSGCombiner3D."""
    lines = [
        '[gd_scene load_steps=2 format=3]',
        f'[ext_resource type="Material" path="{MAT_BASE}/{MAT_WALL}.tres" id="1"]',
        '',
        tsnode("WallCorner01", "CSGCombiner3D", ".", {"use_collision": "false"}),
        tsnode("WallA", "CSGBox3D", "WallCorner01", {
            "operation": "0",
            "size": f"Vector3({U}, {U}, {W})",
            "material": 'ExtResource("1")',
            "use_collision": "true",
            "transform": f"Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, {W/2})",
        }),
        tsnode("WallB", "CSGBox3D", "WallCorner01", {
            "operation": "0",
            "size": f"Vector3({W}, {U}, {U})",
            "material": 'ExtResource("1")',
            "use_collision": "true",
            "transform": f"Transform3D(0, 0, -1, 0, 1, 0, 1, 0, 0, {W/2}, 0, 0)",
        }),
    ]
    return "\n".join(lines) + "\n"


def build_wall_doorway():
    """Wall with door opening (0.80m x 2.00m cutout)."""
    dw, dh = 0.80, 2.00
    off_y = dh/2 - U/2  # bottom-aligned
    lines = [
        '[gd_scene load_steps=2 format=3]',
        f'[ext_resource type="Material" path="{MAT_BASE}/{MAT_WALL}.tres" id="1"]',
        '',
        tsnode("WallDoorway01", "CSGCombiner3D", ".", {"use_collision": "false"}),
        tsnode("MainWall", "CSGBox3D", "WallDoorway01", {
            "operation": "0",
            "size": f"Vector3({U}, {U}, {W})",
            "material": 'ExtResource("1")',
            "use_collision": "true",
        }),
        tsnode("DoorCutout", "CSGBox3D", "WallDoorway01", {
            "operation": "1",
            "size": f"Vector3({dw}, {dh}, {W + 0.04})",
            "use_collision": "true",
            "transform": f"Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, {off_y}, 0)",
        }),
    ]
    return "\n".join(lines) + "\n"


def build_wall_window():
    """Wall with window opening (1.20m x 0.80m cutout, centered slightly above mid)."""
    ww, wh = 1.20, 0.80
    off_y = 0.30
    lines = [
        '[gd_scene load_steps=2 format=3]',
        f'[ext_resource type="Material" path="{MAT_BASE}/{MAT_WALL}.tres" id="1"]',
        '',
        tsnode("WallWindow01", "CSGCombiner3D", ".", {"use_collision": "false"}),
        tsnode("MainWall", "CSGBox3D", "WallWindow01", {
            "operation": "0",
            "size": f"Vector3({U}, {U}, {W})",
            "material": 'ExtResource("1")',
            "use_collision": "true",
        }),
        tsnode("WindowCutout", "CSGBox3D", "WallWindow01", {
            "operation": "1",
            "size": f"Vector3({ww}, {wh}, {W + 0.04})",
            "use_collision": "true",
            "transform": f"Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, {off_y}, 0)",
        }),
    ]
    return "\n".join(lines) + "\n"


def build_wall_endcap():
    """Narrow edge cap — 0.32m x 2.56m x 0.16m."""
    lines = [
        '[gd_scene load_steps=2 format=3]',
        f'[ext_resource type="Material" path="{MAT_BASE}/{MAT_WALL}.tres" id="1"]',
        '',
        tsnode("WallEndcap01", "CSGBox3D", ".", {
            "size": "Vector3(0.32, 2.56, 0.16)",
            "material": 'ExtResource("1")',
            "use_collision": "true",
        }),
    ]
    return "\n".join(lines) + "\n"


# ── Floor pieces ─────────────────────────────────────────────────────────

def build_floor_tile():
    """2.56m x 0.08m x 2.56m floor slab — industrial concrete."""
    lines = [
        f'[gd_scene load_steps=2 format=3]',
        f'[ext_resource type="Material" path="{MAT_BASE}/{MAT_FLOOR}.tres" id="1"]',
        '',
        tsnode("FloorTile01", "CSGBox3D", ".", {
            "size": f"Vector3({U}, {F}, {U})",
            "material": 'ExtResource("1")',
            "use_collision": "true",
        }),
    ]
    return "\n".join(lines) + "\n"


def build_floor_tile_ceramic():
    """Floor slab with ceramic tile material."""
    lines = [
        f'[gd_scene load_steps=2 format=3]',
        f'[ext_resource type="Material" path="{MAT_BASE}/{MAT_FLOOR_TILE}.tres" id="1"]',
        '',
        tsnode("FloorTileCeramic01", "CSGBox3D", ".", {
            "size": f"Vector3({U}, {F}, {U})",
            "material": 'ExtResource("1")',
            "use_collision": "true",
        }),
    ]
    return "\n".join(lines) + "\n"


# ── Structural ───────────────────────────────────────────────────────────

def build_pillar():
    """Square pillar — 0.64m x 2.56m x 0.64m."""
    lines = [
        f'[gd_scene load_steps=2 format=3]',
        f'[ext_resource type="Material" path="{MAT_BASE}/{MAT_WALL2}.tres" id="1"]',
        '',
        tsnode("Pillar01", "CSGBox3D", ".", {
            "size": "Vector3(0.64, 2.56, 0.64)",
            "material": 'ExtResource("1")',
            "use_collision": "true",
        }),
    ]
    return "\n".join(lines) + "\n"


def build_beam():
    """Ceiling beam — 3.84m x 0.32m x 0.32m metal."""
    lines = [
        f'[gd_scene load_steps=2 format=3]',
        f'[ext_resource type="Material" path="{MAT_BASE}/{MAT_METAL}.tres" id="1"]',
        '',
        tsnode("Beam01", "CSGBox3D", ".", {
            "size": f"Vector3({U * 1.5}, 0.32, 0.32)",
            "material": 'ExtResource("1")',
            "use_collision": "true",
        }),
    ]
    return "\n".join(lines) + "\n"


# ── Accent panels ────────────────────────────────────────────────────────

def build_accent_panel(name, mat_name, color_label):
    """A thin accent panel with team color material."""
    lines = [
        f'[gd_scene load_steps=2 format=3]',
        f'[ext_resource type="Material" path="{MAT_BASE}/{mat_name}.tres" id="1"]',
        '',
        tsnode(f"{color_label}Panel01", "CSGBox3D", ".", {
            "size": f"Vector3(1.28, 0.64, {W * 0.5})",
            "material": 'ExtResource("1")',
            "use_collision": "true",
        }),
    ]
    return "\n".join(lines) + "\n"


# ── Kit demo scene ───────────────────────────────────────────────────────

def build_kit_demo():
    """Showcase scene — places every modular piece on a 3m-spaced strip."""
    # Each entry: (scene_name, ext_material_name, label_for_node)
    entries = [
        ("wall_straight_01", MAT_WALL, "Wall01"),
        ("wall_corner_01", MAT_WALL, "Corner01"),
        ("wall_doorway_01", MAT_WALL, "Doorway01"),
        ("wall_window_01", MAT_WALL, "Window01"),
        ("wall_endcap_01", MAT_WALL, "Endcap01"),
        ("floor_tile_01", MAT_FLOOR, "Floor01"),
        ("floor_tile_ceramic_01", MAT_FLOOR_TILE, "FloorCeramic01"),
        ("pillar_01", MAT_WALL2, "Pillar01"),
        ("beam_01", MAT_METAL, "Beam01"),
        ("accent_blue_panel", MAT_BLUE, "BluePanel01"),
        ("accent_red_panel", MAT_RED, "RedPanel01"),
    ]

    # All unique materials used
    all_mats = sorted(set(e[1] for e in entries))
    mat_scene_map = {}  # mat_name -> {scene_name -> ext_id}
    scene_map = {}  # scene_name -> ext_id

    ext_id_counter = 1
    lines = []

    # First pass: assign ext ids to scenes (PackedScene) and materials
    scene_ext_ids = {}
    mat_ext_ids = {}
    for scene_name, mat_name, _ in entries:
        if scene_name not in scene_ext_ids:
            scene_ext_ids[scene_name] = ext_id_counter
            ext_id_counter += 1
        if mat_name not in mat_ext_ids:
            mat_ext_ids[mat_name] = ext_id_counter
            ext_id_counter += 1

    total_ext = len(scene_ext_ids) + len(mat_ext_ids)
    load_steps = total_ext + 1

    lines = [f'[gd_scene load_steps={load_steps} format=3]']

    # Ext resources: scenes
    for scene_name, eid in scene_ext_ids.items():
        lines.append(
            f'[ext_resource type="PackedScene" '
            f'path="res://assets/scenes/modular/{scene_name}.tscn" id="{eid}"]'
        )

    # Ext resources: materials (for any inline nodes)
    for mat_name, eid in mat_ext_ids.items():
        lines.append(
            f'[ext_resource type="Material" '
            f'path="{MAT_BASE}/{mat_name}.tres" id="{eid}"]'
        )

    lines.append("")
    lines.append('[node name="KitDemo" type="Node3D"]')
    lines.append("")

    x = -5.0
    for scene_name, mat_name, label in entries:
        scene_eid = scene_ext_ids[scene_name]
        lines.append(
            f'[node name="{label}" type="Node3D" parent="."]'
        )
        lines.append(f'instance = ExtResource("{scene_eid}")')
        lines.append(f'transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, {x:.1f}, 0, 0)')
        lines.append("")
        x += 3.0

    return "\n".join(lines) + "\n"


# ── Main ─────────────────────────────────────────────────────────────────

SCENE_BUILDERS = {
    "wall_straight_01": build_wall_straight,
    "wall_corner_01": build_wall_corner,
    "wall_doorway_01": build_wall_doorway,
    "wall_window_01": build_wall_window,
    "wall_endcap_01": build_wall_endcap,
    "floor_tile_01": build_floor_tile,
    "floor_tile_ceramic_01": build_floor_tile_ceramic,
    "pillar_01": build_pillar,
    "beam_01": build_beam,
    "accent_blue_panel": lambda: build_accent_panel("accent_blue_panel", MAT_BLUE, "Blue"),
    "accent_red_panel": lambda: build_accent_panel("accent_red_panel", MAT_RED, "Red"),
    "kit_demo": build_kit_demo,
}


def main():
    os.makedirs(SCENES_DIR, exist_ok=True)
    print("Generating modular .tscn scenes...")
    for name, builder in SCENE_BUILDERS.items():
        content = builder()
        path = os.path.join(SCENES_DIR, f"{name}.tscn")
        with open(path, "w") as f:
            f.write(content)
        print(f"  Created {name}.tscn ({len(content)} bytes)")
    print(f"\nDone — {len(SCENE_BUILDERS)} .tscn files")


if __name__ == "__main__":
    main()
