"""Colored GLB straight from the parts — no fuse, no STEP, ~seconds.

The STEP->GLB pipeline drops Compound child colors (the original grey-render
bug, resurfaced in 3D as all-gold-on-black). This exporter tessellates
gen_parts() directly: every part keeps its color as a PBR material and its
node is named stone-N / metal-N / support-N so the viewer can assign real
materials (tinted refractive stones, colored metals).

  .cad-venv/bin/python -m ringcli.glb <generator.py> <out.glb>
"""

from __future__ import annotations

import importlib.util
import sys
from pathlib import Path

import numpy as np
import trimesh

from ringcli.parts import is_metal


def export_parts_glb(gen_path: str, out_glb: str, tol: float = 0.08) -> str:
    gen = Path(gen_path)
    spec = importlib.util.spec_from_file_location("gen_mod", gen)
    mod = importlib.util.module_from_spec(spec)
    sys.path.insert(0, str(gen.parent))
    spec.loader.exec_module(mod)
    parts = mod.gen_parts()

    scene = trimesh.Scene()
    for i, p in enumerate(parts):
        verts, faces = p.tessellate(tol)
        v = np.array([(q.X, q.Y, q.Z) for q in verts])
        f = np.array(faces, dtype=np.int64)
        if not len(f):
            continue
        m = trimesh.Trimesh(v, f, process=False)
        _ = m.vertex_normals          # force normals into the export — glTF
                                      # meshes without NORMAL render black
        c = getattr(p, "color", None)
        rgba = list(tuple(c)[:3] if c else (0.7, 0.7, 0.7)) + [1.0]
        m.visual = trimesh.visual.TextureVisuals(
            material=trimesh.visual.material.PBRMaterial(
                baseColorFactor=rgba,          # glTF: floats 0-1 (255s = black)
                metallicFactor=1.0, roughnessFactor=0.3))
        kind = "metal" if is_metal(p) else "stone"
        scene.add_geometry(m, node_name=f"{kind}-{i}", geom_name=f"{kind}-{i}")
    scene.export(out_glb)
    return out_glb


if __name__ == "__main__":
    print(export_parts_glb(sys.argv[1], sys.argv[2]))
