/**
 * `PartPlacement` — position a part on a surface location.
 *
 * A stable per-part component that places a part at its route's anchor (plus
 * the candidate's anchor when there is one) and applies the route's stacking
 * strategy via `useStacking`. Renders the part's mesh with `PartView`.
 */
import type { Package } from '@tts/bgm';
import { useStacking } from './stacking.js';
import type { Placement } from './state.js';
import { PartView } from './partView.js';
import { MM_TO_WORLD } from './part.js';

export function PartPlacement({ pkg, placement }: { pkg: Package; placement: Placement }) {
  const { route, candidate, piece, index, stackSize } = placement;
  // `piece` is `package:type#id`; the parts map is keyed by `type#id`.
  const part = pkg.parts.get(piece.split(':').slice(1).join(':'));
  if (!part) return null;

  const { x, y, rotation, z, tilt } = useStacking(route.stacking, index, stackSize);

  // Route anchors and stacking offsets are in mm; convert to world units so
  // parts land on the (world-scaled) surface. `z` raises the part along the
  // surface normal (world +Y); `tilt` fans it about its local Y (long) axis.
  const anchorX = ((candidate?.x ?? route.x ?? 0) + x) * MM_TO_WORLD;
  const anchorY = ((candidate?.y ?? route.y ?? 0) + y) * MM_TO_WORLD;
  const anchorZ = z * MM_TO_WORLD;
  const anchorRotation = (candidate?.rotation ?? route.rotation ?? 0) + rotation;

  return (
    <group position={[anchorX, anchorZ, anchorY]} rotation={[0, anchorRotation, 0]}>
      {/* The part mesh extrudes along +Z; lay it flat so its face points up. */}
      <group rotation={[-Math.PI / 2, 0, tilt]}>
        <PartView part={part} baseUrl={part.baseUrl} />
      </group>
    </group>
  );
}
