"use client";

import {
  ContactShadows,
  Environment,
  Float,
  MeshTransmissionMaterial,
  RoundedBox,
  Sparkles,
} from "@react-three/drei";
import { Canvas, useFrame, useThree } from "@react-three/fiber";
import {
  Dispatch,
  MutableRefObject,
  SetStateAction,
  Suspense,
  useMemo,
  useRef,
} from "react";
import * as THREE from "three";

type SceneProps = {
  progressRef: MutableRefObject<number>;
  pointerRef: MutableRefObject<{ x: number; y: number }>;
  setReady: Dispatch<SetStateAction<boolean>>;
};

function damp(current: number, target: number, speed: number, delta: number) {
  return THREE.MathUtils.damp(current, target, speed, delta);
}

function GlassMaterial({
  opacity = 0.34,
  color = "#b9efff",
}: {
  opacity?: number;
  color?: string;
}) {
  return (
    <meshPhysicalMaterial
      color={color}
      transparent
      opacity={opacity}
      roughness={0.08}
      metalness={0.02}
      transmission={0.92}
      thickness={1.1}
      ior={1.45}
      clearcoat={1}
      clearcoatRoughness={0.08}
      envMapIntensity={1.45}
      side={THREE.DoubleSide}
    />
  );
}

function MachineBody() {
  return (
    <group>
      {/* Main lower body */}
      <RoundedBox
        args={[2.65, 1.25, 1.7]}
        radius={0.32}
        smoothness={8}
        position={[0, -0.55, 0]}
        castShadow
        receiveShadow
      >
        <meshPhysicalMaterial
          color="#f8fcff"
          roughness={0.19}
          metalness={0.22}
          clearcoat={1}
          clearcoatRoughness={0.1}
          envMapIntensity={1.6}
        />
      </RoundedBox>

      {/* Dark lower chassis */}
      <RoundedBox
        args={[2.35, 0.42, 1.52]}
        radius={0.18}
        smoothness={6}
        position={[0, -1.15, 0.02]}
        castShadow
      >
        <meshStandardMaterial
          color="#102b3a"
          roughness={0.34}
          metalness={0.52}
        />
      </RoundedBox>

      {/* Transparent water chamber */}
      <RoundedBox
        args={[1.65, 1.55, 1.18]}
        radius={0.34}
        smoothness={8}
        position={[0, 0.65, 0]}
        castShadow
      >
        <MeshTransmissionMaterial
          color="#8de4ff"
          thickness={1.25}
          transmission={1}
          roughness={0.06}
          chromaticAberration={0.035}
          anisotropy={0.2}
          distortion={0.08}
          distortionScale={0.28}
          temporalDistortion={0.06}
          ior={1.38}
          backside
          samples={4}
          resolution={256}
        />
      </RoundedBox>

      {/* Water inside chamber */}
      <RoundedBox
        args={[1.42, 0.72, 0.98]}
        radius={0.23}
        smoothness={6}
        position={[0, 0.36, 0]}
      >
        <meshPhysicalMaterial
          color="#159bd8"
          transparent
          opacity={0.34}
          roughness={0.05}
          transmission={0.25}
          emissive="#0b8bc9"
          emissiveIntensity={0.12}
        />
      </RoundedBox>

      {/* Upper control head */}
      <RoundedBox
        args={[1.85, 0.62, 1.2]}
        radius={0.24}
        smoothness={7}
        position={[0, 1.62, 0]}
        castShadow
      >
        <meshPhysicalMaterial
          color="#ffffff"
          roughness={0.17}
          metalness={0.25}
          clearcoat={1}
        />
      </RoundedBox>

      {/* Front black display */}
      <RoundedBox
        args={[1.05, 0.28, 0.07]}
        radius={0.08}
        smoothness={6}
        position={[0, 1.63, 0.624]}
      >
        <meshPhysicalMaterial
          color="#071a24"
          roughness={0.06}
          metalness={0.65}
          emissive="#0c3043"
          emissiveIntensity={0.38}
        />
      </RoundedBox>

      {/* Display indicator */}
      <mesh position={[0, 1.63, 0.665]}>
        <planeGeometry args={[0.56, 0.045]} />
        <meshBasicMaterial color="#55d8ff" toneMapped={false} />
      </mesh>

      {/* Branded front plate */}
      <RoundedBox
        args={[1.28, 0.34, 0.08]}
        radius={0.1}
        smoothness={5}
        position={[0, -0.55, 0.875]}
      >
        <meshPhysicalMaterial
          color="#eaf9ff"
          roughness={0.16}
          metalness={0.25}
          emissive="#159bd8"
          emissiveIntensity={0.1}
        />
      </RoundedBox>

      {/* Lark Shine symbol */}
      <group position={[0, -0.55, 0.93]}>
        <mesh rotation={[0, 0, Math.PI / 4]}>
          <boxGeometry args={[0.23, 0.23, 0.035]} />
          <meshBasicMaterial color="#159bd8" toneMapped={false} />
        </mesh>

        <mesh position={[0.26, 0, 0]}>
          <boxGeometry args={[0.22, 0.055, 0.035]} />
          <meshBasicMaterial color="#ffffff" toneMapped={false} />
        </mesh>

        <mesh position={[0.48, 0, 0]}>
          <boxGeometry args={[0.12, 0.055, 0.035]} />
          <meshBasicMaterial color="#78ddff" toneMapped={false} />
        </mesh>
      </group>

      {/* Wheels */}
      {[-1, 1].map((side) => (
        <group key={side}>
          <mesh
            position={[side * 1.18, -0.92, 0.12]}
            rotation={[0, 0, Math.PI / 2]}
            castShadow
          >
            <cylinderGeometry args={[0.39, 0.39, 0.24, 32]} />
            <meshStandardMaterial
              color="#0b202b"
              roughness={0.42}
              metalness={0.26}
            />
          </mesh>

          <mesh
            position={[side * 1.305, -0.92, 0.12]}
            rotation={[0, 0, Math.PI / 2]}
          >
            <cylinderGeometry args={[0.17, 0.17, 0.025, 24]} />
            <meshStandardMaterial
              color="#54cbed"
              roughness={0.24}
              metalness={0.48}
            />
          </mesh>
        </group>
      ))}

      {/* Cleaning head */}
      <RoundedBox
        args={[3.15, 0.29, 1.22]}
        radius={0.16}
        smoothness={6}
        position={[0, -1.47, 0.42]}
        castShadow
      >
        <meshPhysicalMaterial
          color="#edfaff"
          roughness={0.2}
          metalness={0.2}
          clearcoat={0.9}
        />
      </RoundedBox>

      <mesh
        position={[0, -1.63, 0.42]}
        rotation={[Math.PI / 2, 0, 0]}
      >
        <cylinderGeometry args={[0.48, 0.48, 0.08, 32]} />
        <meshStandardMaterial
          color="#159bd8"
          roughness={0.38}
          metalness={0.18}
        />
      </mesh>

      {/* Rear handle */}
      <mesh position={[0, 2.66, -0.32]} rotation={[0.13, 0, 0]}>
        <capsuleGeometry args={[0.1, 1.75, 8, 20]} />
        <meshPhysicalMaterial
          color="#d8eef5"
          roughness={0.16}
          metalness={0.72}
        />
      </mesh>

      <RoundedBox
        args={[0.88, 0.22, 0.25]}
        radius={0.1}
        smoothness={5}
        position={[0, 3.52, -0.11]}
        rotation={[0.13, 0, 0]}
      >
        <meshPhysicalMaterial
          color="#102b3a"
          roughness={0.3}
          metalness={0.48}
        />
      </RoundedBox>

      {/* Side lighting */}
      {[-1, 1].map((side) => (
        <mesh
          key={`light-${side}`}
          position={[side * 1.34, -0.45, 0.48]}
          rotation={[0, side * 0.22, 0]}
        >
          <boxGeometry args={[0.035, 0.65, 0.12]} />
          <meshBasicMaterial color="#70dcff" toneMapped={false} />
        </mesh>
      ))}
    </group>
  );
}

function SprayBottle() {
  return (
    <group>
      <RoundedBox
        args={[0.62, 1.22, 0.46]}
        radius={0.17}
        smoothness={6}
        position={[0, -0.18, 0]}
        castShadow
      >
        <MeshTransmissionMaterial
          color="#66d8ff"
          transmission={0.92}
          roughness={0.08}
          thickness={0.85}
          ior={1.4}
          backside
          samples={3}
          resolution={128}
        />
      </RoundedBox>

      <mesh position={[0, 0.54, 0]}>
        <cylinderGeometry args={[0.14, 0.19, 0.28, 24]} />
        <meshStandardMaterial
          color="#f7fcff"
          roughness={0.2}
          metalness={0.2}
        />
      </mesh>

      <RoundedBox
        args={[0.65, 0.17, 0.22]}
        radius={0.07}
        smoothness={4}
        position={[0.18, 0.74, 0]}
      >
        <meshStandardMaterial
          color="#102b3a"
          roughness={0.32}
          metalness={0.45}
        />
      </RoundedBox>

      <mesh position={[0.42, 0.73, 0]}>
        <boxGeometry args={[0.28, 0.08, 0.13]} />
        <meshStandardMaterial color="#159bd8" />
      </mesh>
    </group>
  );
}

function Squeegee() {
  return (
    <group rotation={[0, 0, -0.5]}>
      <RoundedBox
        args={[0.26, 1.35, 0.25]}
        radius={0.11}
        smoothness={5}
        position={[0, -0.4, 0]}
      >
        <meshPhysicalMaterial
          color="#effbff"
          metalness={0.38}
          roughness={0.2}
        />
      </RoundedBox>

      <RoundedBox
        args={[1.55, 0.24, 0.24]}
        radius={0.1}
        smoothness={5}
        position={[0, 0.36, 0]}
      >
        <meshPhysicalMaterial
          color="#159bd8"
          metalness={0.25}
          roughness={0.22}
        />
      </RoundedBox>

      <mesh position={[0, 0.52, 0]}>
        <boxGeometry args={[1.75, 0.08, 0.11]} />
        <meshStandardMaterial
          color="#102b3a"
          roughness={0.38}
          metalness={0.24}
        />
      </mesh>
    </group>
  );
}

function Cloth() {
  return (
    <group rotation={[0.2, -0.38, 0.28]}>
      <RoundedBox
        args={[1.35, 0.09, 1.05]}
        radius={0.18}
        smoothness={7}
        castShadow
      >
        <meshStandardMaterial
          color="#5dd7f4"
          roughness={0.88}
          metalness={0}
        />
      </RoundedBox>

      {[-0.42, 0, 0.42].map((x) => (
        <mesh key={x} position={[x, 0.055, 0]}>
          <boxGeometry args={[0.025, 0.025, 0.82]} />
          <meshBasicMaterial color="#dbfaff" />
        </mesh>
      ))}
    </group>
  );
}

function BrushHead() {
  return (
    <group rotation={[0.35, 0.2, -0.12]}>
      <mesh castShadow>
        <cylinderGeometry args={[0.62, 0.62, 0.24, 40]} />
        <meshPhysicalMaterial
          color="#eefaff"
          roughness={0.23}
          metalness={0.25}
          clearcoat={0.8}
        />
      </mesh>

      <mesh position={[0, -0.17, 0]}>
        <cylinderGeometry args={[0.52, 0.58, 0.16, 40]} />
        <meshStandardMaterial
          color="#159bd8"
          roughness={0.58}
          metalness={0.08}
        />
      </mesh>

      <mesh position={[0, 0.17, 0]}>
        <cylinderGeometry args={[0.18, 0.22, 0.17, 28]} />
        <meshStandardMaterial
          color="#102b3a"
          roughness={0.3}
          metalness={0.48}
        />
      </mesh>
    </group>
  );
}

function WaterDrop({ scale = 1 }: { scale?: number }) {
  return (
    <mesh scale={scale} rotation={[0, 0, Math.PI]}>
      <sphereGeometry args={[0.22, 32, 32]} />
      <MeshTransmissionMaterial
        color="#85e8ff"
        transmission={1}
        roughness={0.02}
        thickness={0.6}
        ior={1.32}
        backside
        samples={3}
        resolution={128}
      />
    </mesh>
  );
}

type BurstParticle = {
  angle: number;
  distance: number;
  height: number;
  size: number;
  speed: number;
  delay: number;
  kind: "drop" | "spark";
};

function CinematicBurst({
  progressRef,
  mobile = false,
}: {
  progressRef: MutableRefObject<number>;
  mobile?: boolean;
}) {
  const group = useRef<THREE.Group>(null);
  const particles = useRef<Array<THREE.Mesh | null>>([]);

  const particleData = useMemo<BurstParticle[]>(
    () =>
      Array.from(
        { length: mobile ? 16 : 34 },
        (_, index) => ({
          angle:
            (index / (mobile ? 16 : 34)) *
              Math.PI *
              2 +
            (index % 4) * 0.28,
          distance:
            1.1 + (index % 7) * 0.34,
          height:
            ((index * 37) % 100) / 100 - 0.5,
          size:
            0.035 + (index % 5) * 0.017,
          speed:
            0.72 + (index % 6) * 0.09,
          delay:
            (index % 8) * 0.035,
          kind:
            index % 3 === 0 ? "spark" : "drop",
        }),
      ),
    [mobile],
  );

  useFrame((state) => {
    if (!group.current) return;

    const p = progressRef.current;

    const transitionPoints = [
      0.2,
      0.46,
      0.71,
      0.88,
    ];

    let nearestDistance = 1;
    let activePoint = 0;

    transitionPoints.forEach((point) => {
      const distance = Math.abs(p - point);

      if (distance < nearestDistance) {
        nearestDistance = distance;
        activePoint = point;
      }
    });

    const burstWindow = mobile ? 0.045 : 0.062;

    const burstStrength =
      nearestDistance < burstWindow
        ? Math.sin(
            (1 - nearestDistance / burstWindow) *
              Math.PI,
          )
        : 0;

    group.current.visible = burstStrength > 0.01;

    const time = state.clock.elapsedTime;

    particles.current.forEach((particle, index) => {
      if (!particle) return;

      const data = particleData[index];

      const localStrength = Math.max(
        0,
        burstStrength - data.delay,
      );

      const animatedDistance =
        data.distance *
        localStrength *
        data.speed;

      particle.position.x =
        Math.cos(data.angle) * animatedDistance;

      particle.position.y =
        Math.sin(data.angle) *
          animatedDistance *
          0.56 +
        data.height *
          localStrength *
          (mobile ? 1.1 : 1.8);

      particle.position.z =
        localStrength *
          (mobile ? 0.55 : 1.85) +
        Math.sin(time * 3 + index) * 0.06;

      particle.rotation.z =
        data.angle +
        time *
          (data.kind === "spark"
            ? 1.8
            : 0.45);

      const scale =
        localStrength *
        (0.3 + data.size * 8);

      particle.scale.setScalar(scale);

      const material = particle.material as
        | THREE.MeshBasicMaterial
        | THREE.MeshPhysicalMaterial;

      material.opacity = Math.min(
        1,
        localStrength * 1.65,
      );
    });

    const machineX =
      activePoint < 0.3
        ? mobile
          ? 0.15
          : 0.5
        : activePoint < 0.6
          ? mobile
            ? -0.25
            : -1.05
          : activePoint < 0.8
            ? mobile
              ? 0.22
              : 0.95
            : 0;

    group.current.position.x = machineX;
    group.current.position.y =
      mobile ? -0.65 : -0.1;
  });

  return (
    <group ref={group}>
      {particleData.map((particle, index) => (
        <mesh
          key={index}
          ref={(element) => {
            particles.current[index] = element;
          }}
        >
          {particle.kind === "spark" ? (
            <octahedronGeometry
              args={[particle.size, 0]}
            />
          ) : (
            <sphereGeometry
              args={[particle.size, 12, 12]}
            />
          )}

          {particle.kind === "spark" ? (
            <meshBasicMaterial
              color="#ffffff"
              transparent
              opacity={0}
              toneMapped={false}
              depthWrite={false}
              blending={THREE.AdditiveBlending}
            />
          ) : (
            <meshPhysicalMaterial
              color="#69ddff"
              transparent
              opacity={0}
              roughness={0.05}
              transmission={0.72}
              thickness={0.3}
              depthWrite={false}
            />
          )}
        </mesh>
      ))}
    </group>
  );
}

function GlassPanel({
  position,
  rotation,
  scale = [3.4, 2.05, 0.08],
  opacity = 0.2,
}: {
  position: [number, number, number];
  rotation: [number, number, number];
  scale?: [number, number, number];
  opacity?: number;
}) {
  return (
    <group position={position} rotation={rotation}>
      <RoundedBox
        args={scale}
        radius={0.17}
        smoothness={7}
        castShadow
      >
        <GlassMaterial opacity={opacity} />
      </RoundedBox>

      <lineSegments>
        <edgesGeometry
          args={[new THREE.BoxGeometry(scale[0], scale[1], scale[2])]}
        />
        <lineBasicMaterial
          color="#b9f2ff"
          transparent
          opacity={0.38}
        />
      </lineSegments>
    </group>
  );
}

function CinematicScene({
  progressRef,
  pointerRef,
  setReady,
}: SceneProps) {
  const world = useRef<THREE.Group>(null);
  const machine = useRef<THREE.Group>(null);
  const orbit = useRef<THREE.Group>(null);
  const panels = useRef<THREE.Group>(null);
  const { camera, size } = useThree();
  const isMobile = size.width < 768;
  const isTablet = size.width >= 768 && size.width < 1100;

  const objectRefs = [
    useRef<THREE.Group>(null),
    useRef<THREE.Group>(null),
    useRef<THREE.Group>(null),
    useRef<THREE.Group>(null),
  ];

  const basePositions = useMemo(
    () => [
      new THREE.Vector3(-3.7, 1.6, 0.1),
      new THREE.Vector3(3.8, 1.25, -0.2),
      new THREE.Vector3(-3.2, -1.9, -0.1),
      new THREE.Vector3(3.25, -1.7, 0.25),
    ],
    [],
  );

  useFrame((state, delta) => {
    const p = progressRef.current;
    const px = pointerRef.current.x;
    const py = pointerRef.current.y;

    const contentCrossStrength =
      p >= 0.08 && p < 0.28
        ? Math.sin(
            ((p - 0.08) / 0.2) * Math.PI,
          )
        : p >= 0.35 && p < 0.56
          ? Math.sin(
              ((p - 0.35) / 0.21) *
                Math.PI,
            )
          : p >= 0.63 && p < 0.82
            ? Math.sin(
                ((p - 0.63) / 0.19) *
                  Math.PI,
              )
            : 0;

    const introPop =
      p < 0.24 ? Math.sin((p / 0.24) * Math.PI) : 0;

    const servicePop =
      p >= 0.24 && p < 0.58
        ? Math.sin(((p - 0.24) / 0.34) * Math.PI)
        : 0;

    const trustPop =
      p >= 0.58 && p < 0.9
        ? Math.sin(((p - 0.58) / 0.32) * Math.PI)
        : 0;

    const popOut = Math.max(
      introPop * 0.9,
      servicePop * 1.12,
      trustPop * 0.86,
    );

    setReady(true);

    if (machine.current) {
      const phaseRotation =
        p < 0.25
          ? p * 1.15
          : p < 0.55
            ? 0.28 + (p - 0.25) * 2.1
            : p < 0.8
              ? 0.91 - (p - 0.55) * 1.5
              : 0.54 + (p - 0.8) * 2.2;

      const targetMachineX =
        p < 0.32
          ? -0.15 + p * 0.58
          : p < 0.64
            ? 0.04 - (p - 0.32) * 0.52
            : -0.12 + (p - 0.64) * 0.34;

      const targetMachineZ =
        popOut * (isMobile ? 0.9 : isTablet ? 1.35 : 2.05);

      machine.current.position.x = damp(
        machine.current.position.x,
        targetMachineX + px * (isMobile ? 0.05 : isTablet ? 0.09 : 0.14),
        3.5,
        delta,
      );

      machine.current.position.z = damp(
        machine.current.position.z,
        targetMachineZ,
        3.8,
        delta,
      );

      machine.current.rotation.y = damp(
        machine.current.rotation.y,
        phaseRotation + px * 0.18 + popOut * 0.12,
        3.8,
        delta,
      );

      machine.current.rotation.x = damp(
        machine.current.rotation.x,
        -0.08 + py * 0.08 - popOut * 0.05,
        3.8,
        delta,
      );

      machine.current.rotation.z = damp(
        machine.current.rotation.z,
        Math.sin(p * Math.PI * 6) * 0.025 + px * 0.02,
        3.8,
        delta,
      );

      const targetY =
        p < 0.3
          ? -0.05 + p * 0.4
          : p < 0.68
            ? 0.08 - (p - 0.3) * 0.7
            : -0.19 + (p - 0.68) * 0.9;

      const responsiveTargetY =
        targetY + (isMobile ? -0.72 : isTablet ? -0.18 : 0);

      machine.current.position.y = damp(
        machine.current.position.y,
        responsiveTargetY,
        3.5,
        delta,
      );

      const targetScale =
        p < 0.22
          ? 0.92 + p * 0.36
          : p < 0.62
            ? 1
            : 1 - (p - 0.62) * 0.2;

      const responsiveScale =
        targetScale *
        (isMobile ? 0.57 : isTablet ? 0.78 : 1) *
        (1 + popOut * 0.08);

      machine.current.scale.setScalar(
        damp(
          machine.current.scale.x,
          responsiveScale,
          3.4,
          delta,
        ),
      );
    }

    if (orbit.current) {
      orbit.current.rotation.y = damp(
        orbit.current.rotation.y,
        p * 1.3 + px * 0.12,
        2.8,
        delta,
      );

      orbit.current.rotation.z = damp(
        orbit.current.rotation.z,
        Math.sin(p * Math.PI * 4) * 0.16 +
          px * 0.055,
        2.8,
        delta,
      );

      orbit.current.position.z = damp(
        orbit.current.position.z,
        Math.sin(p * Math.PI * 3) *
          (isMobile ? 0.42 : 0.95),
        3,
        delta,
      );
    }

    const separation =
      p < 0.2
        ? 0.76
        : p < 0.54
          ? 0.76 + (p - 0.2) * 2.7
          : p < 0.78
            ? 1.68 - (p - 0.54) * 1.8
            : 1.25;

    objectRefs.forEach((ref, index) => {
      if (!ref.current) return;

      const base = basePositions[index];
      const responsiveOrbitScale =
        isMobile ? 0.52 : isTablet ? 0.76 : 1;

      const flyPhase = p * Math.PI * 2;

      const horizontalFly =
        Math.sin(flyPhase + index * 1.45) *
        (isMobile ? 0.65 : 1.45);

      const verticalFly =
        Math.cos(flyPhase * 0.82 + index * 1.1) *
        (isMobile ? 0.38 : 0.82);

      const crossingDirection =
        index % 2 === 0 ? -1 : 1;

      const screenCross =
        contentCrossStrength *
        crossingDirection *
        (isMobile
          ? 0.42 + index * 0.05
          : 1.3 + index * 0.22);

      const screenLift =
        contentCrossStrength *
        (index === 0
          ? 0.7
          : index === 1
            ? -0.42
            : index === 2
              ? 0.28
              : -0.62);

      const targetX =
        base.x *
          separation *
          responsiveOrbitScale +
        horizontalFly +
        screenCross;

      const targetY =
        base.y *
          separation *
          0.78 *
          responsiveOrbitScale +
        verticalFly +
        screenLift;

      const forwardBurst =
        popOut * (0.72 + index * 0.12) +
        Math.max(0, Math.sin(p * Math.PI * 4 + index * 1.2)) *
          (isMobile ? 0.18 : 0.34);

      ref.current.position.x = damp(
        ref.current.position.x,
        targetX,
        3.5,
        delta,
      );

      ref.current.position.y = damp(
        ref.current.position.y,
        targetY,
        3.5,
        delta,
      );

      ref.current.position.z = damp(
        ref.current.position.z,
        base.z +
          Math.sin(p * Math.PI * 2 + index) *
            (isMobile ? 0.22 : 0.48) +
          forwardBurst *
            (isMobile ? 1.05 : isTablet ? 1.7 : 2.45) +
          contentCrossStrength *
            (index % 2 === 0
              ? isMobile
                ? 0.8
                : 2.6
              : isMobile
                ? 0.45
                : 1.7),
        3,
        delta,
      );

      const accessoryScale =
        (isMobile ? 0.66 : isTablet ? 0.84 : 1) *
        (1 + popOut * 0.12) *
        (1 +
          contentCrossStrength *
            (isMobile ? 0.08 : 0.2));

      ref.current.scale.setScalar(
        damp(
          ref.current.scale.x,
          accessoryScale,
          3.5,
          delta,
        ),
      );

      ref.current.rotation.y += delta * (0.17 + index * 0.025);
      ref.current.rotation.x += delta * (0.035 + index * 0.01);

      ref.current.rotation.z = damp(
        ref.current.rotation.z,
        Math.sin(p * 8 + index * 1.45) * 0.28,
        2.8,
        delta,
      );
    });

    if (panels.current) {
      panels.current.visible = !isMobile;

      panels.current.scale.setScalar(
        damp(
          panels.current.scale.x,
          isTablet ? 0.82 : 1,
          3,
          delta,
        ),
      );

      panels.current.rotation.y = damp(
        panels.current.rotation.y,
        -0.12 + p * 0.42 + px * 0.03,
        3.2,
        delta,
      );

      panels.current.position.z = damp(
        panels.current.position.z,
        p < 0.45 ? -1.2 : -0.3,
        3.1,
        delta,
      );
    }

    const desktopCameraX =
      p < 0.28
        ? 0.15
        : p < 0.55
          ? -1.2
          : p < 0.79
            ? 1.35
            : 0.25;

    const cameraX = isMobile
      ? 0
      : isTablet
        ? desktopCameraX * 0.6
        : desktopCameraX;

    const desktopCameraY =
      p < 0.3
        ? 0.15
        : p < 0.65
          ? 0.42
          : -0.08;

    const cameraY =
      desktopCameraY + (isMobile ? 0.62 : 0);

    const desktopCameraZ =
      p < 0.2
        ? 9.8
        : p < 0.55
          ? 9.05
          : p < 0.8
            ? 9.7
            : 8.55;

    const cameraZ =
      desktopCameraZ +
      (isMobile ? 4.2 : isTablet ? 1.8 : 0) -
      popOut * (isMobile ? 0.35 : isTablet ? 0.85 : 1.35);

    camera.position.x = damp(
      camera.position.x,
      cameraX + px * (isMobile ? 0.08 : 0.48),
      2.8,
      delta,
    );
    camera.position.y = damp(
      camera.position.y,
      cameraY - py * (isMobile ? 0.06 : 0.28),
      2.8,
      delta,
    );
    camera.position.z = damp(
      camera.position.z,
      cameraZ,
      2.8,
      delta,
    );

    const targetFov = isMobile ? 44 : isTablet ? 41 : 38;

    if (camera instanceof THREE.PerspectiveCamera) {
      if (Math.abs(camera.fov - targetFov) > 0.01) {
        camera.fov = damp(
          camera.fov,
          targetFov,
          3,
          delta,
        );
        camera.updateProjectionMatrix();
      }
    }

    camera.lookAt(
      0,
      isMobile ? -0.3 : 0.15,
      0,
    );

    if (world.current) {
      let worldX = 0;
      let worldY = 0;
      let worldZ = 0;

      if (p < 0.2) {
        const t = p / 0.2;

        worldX = THREE.MathUtils.lerp(
          isMobile ? 0.72 : 1.55,
          isMobile ? 0.12 : 0.48,
          t,
        );

        worldY = THREE.MathUtils.lerp(
          isMobile ? -0.42 : 0.08,
          isMobile ? -0.78 : -0.04,
          t,
        );

        worldZ = THREE.MathUtils.lerp(0.2, 1.45, t);
      } else if (p < 0.46) {
        const t = (p - 0.2) / 0.26;

        worldX = THREE.MathUtils.lerp(
          isMobile ? 0.12 : 0.48,
          isMobile ? -0.5 : -1.55,
          t,
        );

        worldY = THREE.MathUtils.lerp(
          isMobile ? -0.78 : -0.04,
          isMobile ? -0.18 : 0.32,
          t,
        );

        worldZ = THREE.MathUtils.lerp(1.45, 0.45, t);
      } else if (p < 0.72) {
        const t = (p - 0.46) / 0.26;

        worldX = THREE.MathUtils.lerp(
          isMobile ? -0.5 : -1.55,
          isMobile ? 0.42 : 1.25,
          t,
        );

        worldY = THREE.MathUtils.lerp(
          isMobile ? -0.18 : 0.32,
          isMobile ? -0.62 : -0.32,
          t,
        );

        worldZ = THREE.MathUtils.lerp(0.45, 1.72, t);
      } else {
        const t = (p - 0.72) / 0.28;

        worldX = THREE.MathUtils.lerp(
          isMobile ? 0.42 : 1.25,
          0,
          t,
        );

        worldY = THREE.MathUtils.lerp(
          isMobile ? -0.62 : -0.32,
          isMobile ? -0.42 : 0,
          t,
        );

        worldZ = THREE.MathUtils.lerp(1.72, 0.25, t);
      }

      world.current.position.x = damp(
        world.current.position.x,
        worldX + px * (isMobile ? 0.08 : 0.2),
        3.4,
        delta,
      );

      world.current.position.y = damp(
        world.current.position.y,
        worldY - py * (isMobile ? 0.05 : 0.12),
        3.4,
        delta,
      );

      world.current.position.z = damp(
        world.current.position.z,
        worldZ,
        3.6,
        delta,
      );

      world.current.rotation.y = damp(
        world.current.rotation.y,
        p < 0.46
          ? -0.12 + p * 0.8
          : 0.26 - (p - 0.46) * 0.54,
        3.2,
        delta,
      );
    }

    state.gl.setClearColor("#07151d", 0);
  });

  return (
    <group ref={world}>
      <ambientLight intensity={0.65} />

      <directionalLight
        position={[5, 7, 6]}
        intensity={3.2}
        color="#d9f7ff"
        castShadow
        shadow-mapSize-width={1024}
        shadow-mapSize-height={1024}
      />

      <directionalLight
        position={[-5, 2, 4]}
        intensity={2.1}
        color="#149bd8"
      />

      <pointLight
        position={[0, -1.8, 3.5]}
        intensity={14}
        distance={12}
        color="#3dd7ff"
      />

      <pointLight
        position={[3.8, 3.3, -1.5]}
        intensity={10}
        distance={11}
        color="#d3f7ff"
      />

      <group ref={panels}>
        <GlassPanel
          position={[-4.6, 1.85, -2.1]}
          rotation={[0.04, 0.34, -0.05]}
          scale={[3.2, 1.95, 0.08]}
          opacity={0.16}
        />

        <GlassPanel
          position={[4.65, -1.45, -2.4]}
          rotation={[-0.03, -0.38, 0.05]}
          scale={[3.5, 2.1, 0.08]}
          opacity={0.15}
        />

        <GlassPanel
          position={[4.8, 2.2, -3.6]}
          rotation={[0.08, -0.42, 0.04]}
          scale={[2.5, 1.45, 0.07]}
          opacity={0.1}
        />
      </group>

      <Float
        speed={1.35}
        rotationIntensity={0.08}
        floatIntensity={0.22}
      >
        <group ref={machine}>
          <MachineBody />
        </group>
      </Float>

      <group ref={orbit}>
        <Float speed={1.7} floatIntensity={0.72} rotationIntensity={0.14}>
          <group ref={objectRefs[0]}>
            <SprayBottle />
          </group>
        </Float>

        <Float speed={1.55} floatIntensity={0.6} rotationIntensity={0.12}>
          <group ref={objectRefs[1]}>
            <Squeegee />
          </group>
        </Float>

        <Float speed={1.8} floatIntensity={0.64} rotationIntensity={0.15}>
          <group ref={objectRefs[2]}>
            <Cloth />
          </group>
        </Float>

        <Float speed={1.45} floatIntensity={0.7} rotationIntensity={0.13}>
          <group ref={objectRefs[3]}>
            <BrushHead />
          </group>
        </Float>
      </group>

      <Float speed={1.8} floatIntensity={1.1} rotationIntensity={0.18}>
        <group position={[-2.1, 2.95, 0.5]}>
          <WaterDrop scale={0.72} />
        </group>
      </Float>

      <Float speed={1.55} floatIntensity={0.8} rotationIntensity={0.16}>
        <group position={[2.45, 2.75, -0.65]}>
          <WaterDrop scale={0.44} />
        </group>
      </Float>

      <Float speed={2.1} floatIntensity={0.75} rotationIntensity={0.2}>
        <group position={[2.2, -2.55, 0.25]}>
          <WaterDrop scale={0.58} />
        </group>
      </Float>

      <CinematicBurst
        progressRef={progressRef}
        mobile={isMobile}
      />

      <Sparkles
        count={isMobile ? 18 : 42}
        scale={[11, 8, 6]}
        size={1.55}
        speed={0.22}
        opacity={0.24}
        color="#b8efff"
      />

      <ContactShadows
        position={[0, -2.15, 0]}
        opacity={0.42}
        scale={9}
        blur={2.5}
        far={5}
      />

      <Environment preset="city" />
    </group>
  );
}

export default function LarkShine3DScene({
  progressRef,
  pointerRef,
  setReady,
}: SceneProps) {
  return (
    <Canvas
      dpr={[1, 1.65]}
      gl={{
        antialias: true,
        alpha: true,
        powerPreference: "high-performance",
      }}
      camera={{
        position: [0, 0.15, 9.8],
        fov: 38,
        near: 0.1,
        far: 100,
      }}
      shadows
    >
      <Suspense fallback={null}>
        <CinematicScene
          progressRef={progressRef}
          pointerRef={pointerRef}
          setReady={setReady}
        />
      </Suspense>
    </Canvas>
  );
}
