import { Canvas } from '@react-three/fiber';
import { Environment, Html, OrbitControls } from '@react-three/drei';
import type { ElementType, FpElement } from './floorplan';

interface Props {
    elements: FpElement[];
    roomWidth: number;
    roomHeight: number;
}

const ELEMENT_HEIGHT: Record<ElementType, number> = {
    round_table:      0.75,
    rect_table:       0.75,
    sweetheart_table: 0.75,
    buffet_table:     0.85,
    gift_table:       0.75,
    cake_table:       0.85,
    dance_floor:      0.05,
    dj_booth:         1.20,
    stage:            0.45,
    bar:              1.10,
    lounge:           0.45,
    photo_booth:      2.20,
    altar:            1.10,
    arch:             2.50,
};

const ELEMENT_COLOR: Record<ElementType, string> = {
    round_table:      '#fbcfd1',
    rect_table:       '#fbcfd1',
    sweetheart_table: '#f4a8af',
    buffet_table:     '#e8c994',
    gift_table:       '#dcc28b',
    cake_table:       '#f7c8d8',
    dance_floor:      '#c8b9e6',
    dj_booth:         '#202023',
    stage:            '#a3c69b',
    bar:              '#3a2a2a',
    lounge:           '#e0cab8',
    photo_booth:      '#eddfb6',
    altar:            '#f0d8b3',
    arch:             '#e9b6bd',
};

export default function FloorPlan3D({ elements, roomWidth, roomHeight }: Props) {
    return (
        <div style={{ width: '100%', height: '100%', minHeight: 480 }}>
            <Canvas
                shadows
                camera={{ position: [roomWidth * 0.7, roomWidth * 0.6, roomHeight * 0.9], fov: 50 }}
                gl={{ preserveDrawingBuffer: true, antialias: true }}
            >
                <ambientLight intensity={0.4} />
                <directionalLight
                    position={[roomWidth, roomWidth * 1.2, roomHeight]}
                    intensity={0.85}
                    castShadow
                    shadow-mapSize-width={1024}
                    shadow-mapSize-height={1024}
                />
                <Environment preset="apartment" />

                {/* Floor */}
                <mesh receiveShadow rotation={[-Math.PI / 2, 0, 0]} position={[roomWidth / 2, 0, roomHeight / 2]}>
                    <planeGeometry args={[roomWidth, roomHeight]} />
                    <meshStandardMaterial color="#f5e8d8" />
                </mesh>

                {/* Walls (low so the camera can see in) */}
                <Wall x={0}            z={roomHeight / 2} w={0.05}        h={1.5} d={roomHeight} />
                <Wall x={roomWidth}    z={roomHeight / 2} w={0.05}        h={1.5} d={roomHeight} />
                <Wall x={roomWidth / 2} z={0}             w={roomWidth}   h={1.5} d={0.05} />
                <Wall x={roomWidth / 2} z={roomHeight}    w={roomWidth}   h={1.5} d={0.05} />

                {/* Elements */}
                {elements.map(el => (
                    <Element3D key={el.id} el={el} />
                ))}

                <OrbitControls makeDefault target={[roomWidth / 2, 0, roomHeight / 2]} />
            </Canvas>
        </div>
    );
}

function Wall({ x, z, w, h, d }: { x: number; z: number; w: number; h: number; d: number }) {
    return (
        <mesh position={[x, h / 2, z]} receiveShadow castShadow>
            <boxGeometry args={[w, h, d]} />
            <meshStandardMaterial color="#ffffff" />
        </mesh>
    );
}

function Element3D({ el }: { el: FpElement }) {
    const height = ELEMENT_HEIGHT[el.type];
    const color = ELEMENT_COLOR[el.type];
    const cx = el.x + el.width / 2;
    const cz = el.y + el.height / 2;
    const isRound = el.type === 'round_table';
    const rotY = (-el.rotation * Math.PI) / 180;

    return (
        <group position={[cx, 0, cz]} rotation={[0, rotY, 0]}>
            {isRound ? (
                <mesh position={[0, height / 2, 0]} castShadow receiveShadow>
                    <cylinderGeometry args={[el.width / 2, el.width / 2, height, 32]} />
                    <meshStandardMaterial color={color} />
                </mesh>
            ) : (
                <mesh position={[0, height / 2, 0]} castShadow receiveShadow>
                    <boxGeometry args={[el.width, height, el.height]} />
                    <meshStandardMaterial color={color} />
                </mesh>
            )}
            <Html
                position={[0, height + 0.2, 0]}
                center
                style={{
                    background: 'rgba(255,255,255,0.85)',
                    padding: '2px 6px',
                    borderRadius: 4,
                    fontSize: 10,
                    fontFamily: 'system-ui',
                    whiteSpace: 'nowrap',
                    pointerEvents: 'none',
                }}
            >
                {el.label}{el.seats > 0 ? ` · ${el.seats}` : ''}
            </Html>
        </group>
    );
}
