
import { useEffect, useMemo, useRef, useState } from 'react'
import { Canvas, useFrame, useThree } from '@react-three/fiber'
import * as THREE from 'three'

const STEPS = [
    {
        label: 'Step 1: Group at rest',
        detail: 'Parent group is centered and children keep their offsets.',
        cameraPosition: [0, 1.7, 6],
        lookAt: [0, 0, 0],
        groupPosition: [0, 0, 0],
        groupRotation: [0, 0, 0],
        spinSpeed: 0,
    },
    {
        label: 'Step 2: Parent rotation',
        detail: 'Only parent rotates; children move together without changing local layout.',
        cameraPosition: [1.7, 1.8, 5.6],
        lookAt: [0, 0, 0],
        groupPosition: [0, 0, 0],
        groupRotation: [0.15, 0.55, 0],
        spinSpeed: 0.015,
    },
    {
        label: 'Step 3: Parent move + rotate',
        detail: 'Parent shifts and rotates as one unit while child spacing stays intact.',
        cameraPosition: [0.6, 2.4, 7],
        lookAt: [0.4, 0.35, 0],
        groupPosition: [0.7, 0.4, -0.4],
        groupRotation: [0.35, 1.2, 0.2],
        spinSpeed: 0.03,
    },
]

function GuidedGroupScene({ stepIndex }) {
    const { camera } = useThree()
    const groupRef = useRef()

    const targets = useMemo(
        () => ({
            cameraPosition: new THREE.Vector3(),
            cameraLookAt: new THREE.Vector3(),
            lookCurrent: new THREE.Vector3(),
            groupPosition: new THREE.Vector3(),
            groupRotation: new THREE.Euler(),
            spinSpeed: 0,
            initialized: false,
        }),
        []
    )

    useEffect(() => {
        const step = STEPS[stepIndex]

        targets.cameraPosition.set(...step.cameraPosition)
        targets.cameraLookAt.set(...step.lookAt)
        targets.groupPosition.set(...step.groupPosition)
        targets.groupRotation.set(...step.groupRotation)
        targets.spinSpeed = step.spinSpeed

        if (groupRef.current && !targets.initialized) {
            camera.position.copy(targets.cameraPosition)
            targets.lookCurrent.copy(targets.cameraLookAt)
            groupRef.current.position.copy(targets.groupPosition)
            groupRef.current.rotation.copy(targets.groupRotation)
            targets.initialized = true
        }
    }, [camera, stepIndex, targets])

    useFrame(() => {
        if (!groupRef.current) return

        groupRef.current.position.lerp(targets.groupPosition, 0.1)

        groupRef.current.rotation.x += (targets.groupRotation.x - groupRef.current.rotation.x) * 0.1
        groupRef.current.rotation.y += (targets.groupRotation.y - groupRef.current.rotation.y) * 0.1
        groupRef.current.rotation.z += (targets.groupRotation.z - groupRef.current.rotation.z) * 0.1

        groupRef.current.rotation.y += targets.spinSpeed * 0.2

        camera.position.lerp(targets.cameraPosition, 0.08)
        targets.lookCurrent.lerp(targets.cameraLookAt, 0.08)
        camera.lookAt(targets.lookCurrent)
    })

    return (
        <>
            <ambientLight intensity={0.8} />
            <directionalLight intensity={1} position={[4, 5, 4]} />

            <mesh rotation={[-Math.PI / 2, 0, 0]} position={[0, -1.2, 0]}>
                <planeGeometry args={[12, 12]} />
                <meshStandardMaterial color="#dde7f3" roughness={0.95} />
            </mesh>

            <group ref={groupRef}>
                <mesh position={[-1.1, 0, 0]}>
                    <boxGeometry args={[0.9, 0.9, 0.9]} />
                    <meshStandardMaterial color="#2a9d8f" />
                </mesh>

                <mesh position={[1.1, 0, 0]}>
                    <sphereGeometry args={[0.55, 24, 24]} />
                    <meshStandardMaterial color="#e76f51" />
                </mesh>

                <mesh position={[0, 0.95, 0]}>
                    <coneGeometry args={[0.42, 0.85, 24]} />
                    <meshStandardMaterial color="#457b9d" />
                </mesh>
            </group>
        </>
    )
}

export default function App() {
    const [stepIndex, setStepIndex] = useState(0)
    const step = STEPS[stepIndex]

    useEffect(() => {
        function onKeyDown(event) {
            if (event.key === '1') setStepIndex(0)
            if (event.key === '2') setStepIndex(1)
            if (event.key === '3') setStepIndex(2)
        }

        window.addEventListener('keydown', onKeyDown)
        return () => window.removeEventListener('keydown', onKeyDown)
    }, [])

    return (
        <div className="app-shell">
            <div id="guide">
                <h2>Task 4: Group Motion</h2>
                <p id="step-label">{step.label}</p>
                <p id="step-detail">{step.detail}</p>

                <div className="row">
                    {STEPS.map((_, index) => (
                        <button
                            key={index}
                            className={`step-btn ${stepIndex === index ? 'active' : ''}`}
                            onClick={() => setStepIndex(index)}
                        >
                            Step {index + 1}
                        </button>
                    ))}
                </div>

                <div className="row">
                    <button onClick={() => setStepIndex((value) => Math.max(value - 1, 0))} disabled={stepIndex === 0}>
                        Previous
                    </button>
                    <button
                        onClick={() => setStepIndex((value) => Math.min(value + 1, STEPS.length - 1))}
                        disabled={stepIndex === STEPS.length - 1}
                    >
                        Next
                    </button>
                </div>

                <p id="hint">Simple parent group animation. Keys: 1, 2, 3.</p>
            </div>

            <Canvas camera={{ fov: 55, near: 0.1, far: 100, position: [0, 1.7, 6] }}>
                <color attach="background" args={['#edf3fa']} />
                <GuidedGroupScene stepIndex={stepIndex} />
            </Canvas>
        </div>
    )
}
