import { useMemo } from 'react';
import * as THREE from 'three';
import type { Wall, WallOpening } from '@house-plan-maker/shared';
import {
  splitWallAroundOpenings,
  wallRotationY,
  wallSegmentCenter3D,
  type WallSegment,
} from './utils/wallGeometry';

interface WallMeshProps {
  readonly wall: Wall;
  readonly openings: readonly WallOpening[];
  readonly wallHeight: number;
  readonly wallColor?: string;
  readonly selectedIds: ReadonlySet<string>;
  readonly onSelect?: (id: string) => void;
}

const DEFAULT_WALL_COLOR = '#f0ebe3';
const WALL_SELECTED_COLOR = '#b8d4e3';

// ── Wall material cache ──
const wallMaterialCache = new Map<string, THREE.MeshStandardMaterial>();

function getWallMaterial(color: string): THREE.MeshStandardMaterial {
  let mat = wallMaterialCache.get(color);
  if (!mat) {
    mat = new THREE.MeshStandardMaterial({ color, roughness: 0.7, side: THREE.DoubleSide });
    wallMaterialCache.set(color, mat);
  }
  return mat;
}

const wallSelectedMaterial = new THREE.MeshStandardMaterial({
  color: WALL_SELECTED_COLOR,
  roughness: 0.7,
  side: THREE.DoubleSide,
});

function WallSegmentMesh({
  wall,
  segment,
  thickness,
  wallColor,
  isSelected,
  onSelect,
}: {
  readonly wall: Wall;
  readonly segment: WallSegment;
  readonly thickness: number;
  readonly wallColor: string;
  readonly isSelected: boolean;
  readonly onSelect?: (id: string) => void;
}) {
  const segmentWidth = segment.endAlongWall - segment.startAlongWall;
  const segmentHeight = segment.topY - segment.bottomY;

  const center = useMemo(
    () => wallSegmentCenter3D(wall, segment),
    [wall, segment],
  );

  const rotY = useMemo(() => wallRotationY(wall), [wall]);

  if (segmentWidth <= 0 || segmentHeight <= 0) return null;

  return (
    <mesh
      position={center}
      rotation={[0, rotY, 0]}
      castShadow
      receiveShadow
      material={isSelected ? wallSelectedMaterial : getWallMaterial(wallColor)}
      onClick={onSelect ? (e) => { e.stopPropagation(); onSelect(wall.id); } : undefined}
    >
      <boxGeometry args={[segmentWidth, segmentHeight, thickness]} />
    </mesh>
  );
}

export function WallMesh({ wall, openings, wallHeight, wallColor = DEFAULT_WALL_COLOR, selectedIds, onSelect }: WallMeshProps) {
  const segments = useMemo(
    () => splitWallAroundOpenings(wall, openings, wallHeight),
    [wall, openings, wallHeight],
  );

  const isSelected = selectedIds.has(wall.id);

  return (
    <group>
      {segments.map((segment, i) => (
        <WallSegmentMesh
          key={`${wall.id}-seg-${i}`}
          wall={wall}
          segment={segment}
          thickness={wall.thickness}
          wallColor={wallColor}
          isSelected={isSelected}
          onSelect={onSelect}
        />
      ))}
    </group>
  );
}
