"use client";

import React, { useMemo, useRef } from "react";
import { useFrame } from "@react-three/fiber";
import * as THREE from "three";
import { C, P } from "./theme";
import { clamp01, damp, lerp, seeded, smoothstep } from "./math";

type Props = {
  progress: React.RefObject<number>;
  reduced?: boolean;
  isMobile?: boolean;
};

/**
 * A giant holographic SLA clock that rises out of the city. As it sweeps,
 * delayed routes flash red and dissolve into a burst of particles — the brain
 * rejecting them — while the reliable routes are left glowing.
 */
function SLAClock({ progress, isMobile = false }: Props) {
  const eased = useRef(0);
  const group = useRef<THREE.Group>(null);
  const hand = useRef<THREE.Mesh>(null);
  const sweepMat = useRef<THREE.MeshBasicMaterial>(null);
  const faceMats = useRef<THREE.MeshBasicMaterial[]>([]);
  const burst = useRef<THREE.Points>(null);
  const redMat = useRef<THREE.MeshBasicMaterial>(null);

  const burstCount = isMobile ? 90 : 180;

  // Random outward directions for the dissolve burst.
  const burstDirs = useMemo(() => {
    const arr: THREE.Vector3[] = [];
    for (let i = 0; i < burstCount; i++) {
      const a = seeded(i * 2.7) * Math.PI * 2;
      const up = 0.3 + seeded(i * 5.1) * 1.4;
      const sp = 0.4 + seeded(i * 3.3) * 1.0;
      arr.push(new THREE.Vector3(Math.cos(a) * sp, up, Math.sin(a) * sp));
    }
    return arr;
  }, [burstCount]);
  const burstGeom = useMemo(() => {
    const g = new THREE.BufferGeometry();
    g.setAttribute("position", new THREE.BufferAttribute(new Float32Array(burstCount * 3), 3));
    return g;
  }, [burstCount]);

  // A "delayed" route arc that gets rejected.
  const redTube = useMemo(() => {
    const c = new THREE.CatmullRomCurve3([
      new THREE.Vector3(-6, 0.3, 5),
      new THREE.Vector3(-2, 1.6, 1),
      new THREE.Vector3(3, 0.3, -4),
    ]);
    return new THREE.TubeGeometry(c, 50, 0.07, 8, false);
  }, []);
  const burstOrigin = useMemo(() => new THREE.Vector3(-2, 0.6, 1), []);

  useFrame((state, dt) => {
    const p = progress.current ?? 0;
    eased.current = damp(eased.current, p, 3, dt);
    const e = eased.current;
    const t = state.clock.elapsedTime;

    const slaIn = smoothstep(P.sla - 0.03, P.sla + 0.05, e);
    const slaOut = 1 - smoothstep(P.ecosystem, P.ecosystem + 0.08, e);
    const active = slaIn * slaOut;

    if (group.current) {
      group.current.visible = active > 0.02;
      group.current.position.y = lerp(2.6, 4.6, slaIn);
      group.current.scale.setScalar(0.0001 + active * 1.5);
      group.current.rotation.z = Math.sin(t * 0.3) * 0.02;
    }
    if (hand.current) hand.current.rotation.z = -t * 1.4;
    if (sweepMat.current) sweepMat.current.opacity = active * (0.6 + Math.sin(t * 4) * 0.2);
    faceMats.current.forEach((m) => { if (m) m.opacity = active * 0.8; });

    // Delayed route flashes red then dissolves.
    const flash = smoothstep(P.sla + 0.02, P.sla + 0.08, e);
    const dissolve = ((t * 0.45) % 1);
    if (redMat.current) {
      redMat.current.opacity = active * flash * (1 - dissolve) * (0.6 + Math.sin(t * 6) * 0.4);
    }
    if (burst.current) {
      const attr = burst.current.geometry.getAttribute("position") as THREE.BufferAttribute;
      const r = dissolve * 3.4;
      for (let i = 0; i < burstDirs.length; i++) {
        const d = burstDirs[i];
        attr.setXYZ(
          i,
          burstOrigin.x + d.x * r,
          burstOrigin.y + d.y * r - dissolve * dissolve * 1.2,
          burstOrigin.z + d.z * r,
        );
      }
      attr.needsUpdate = true;
      (burst.current.material as THREE.PointsMaterial).opacity = clamp01(active * flash * (1 - dissolve));
    }
  });

  return (
    <group>
      {/* Holographic clock */}
      <group ref={group} position={[0, 7, 0]} visible={false}>
        {/* Outer ring */}
        <mesh>
          <torusGeometry args={[1, 0.03, 12, 64]} />
          <meshBasicMaterial color={C.cyan} toneMapped={false} transparent opacity={0.8} blending={THREE.AdditiveBlending} depthWrite={false} />
        </mesh>
        {/* Inner ring */}
        <mesh>
          <torusGeometry args={[0.78, 0.012, 10, 64]} />
          <meshBasicMaterial color={C.blue} toneMapped={false} transparent opacity={0.5} blending={THREE.AdditiveBlending} depthWrite={false} />
        </mesh>
        {/* Tick marks */}
        {Array.from({ length: 12 }).map((_, i) => {
          const a = (i / 12) * Math.PI * 2;
          return (
            <mesh key={i} position={[Math.cos(a) * 0.88, Math.sin(a) * 0.88, 0]} rotation={[0, 0, a]}>
              <boxGeometry args={[0.1, 0.02, 0.02]} />
              <meshBasicMaterial
                ref={(el) => { if (el) faceMats.current[i] = el; }}
                color={i % 3 === 0 ? C.white : C.cyan}
                toneMapped={false}
                transparent
                opacity={0.8}
                blending={THREE.AdditiveBlending}
                depthWrite={false}
              />
            </mesh>
          );
        })}
        {/* Sweeping hand */}
        <mesh ref={hand} position={[0, 0, 0.02]}>
          <boxGeometry args={[0.04, 1.5, 0.02]} />
          <meshBasicMaterial ref={sweepMat} color={C.green} toneMapped={false} transparent opacity={0.7} blending={THREE.AdditiveBlending} depthWrite={false} />
        </mesh>
        {/* Hub */}
        <mesh>
          <sphereGeometry args={[0.07, 16, 16]} />
          <meshBasicMaterial color={C.white} toneMapped={false} />
        </mesh>
      </group>

      {/* Delayed route + dissolve burst */}
      <mesh geometry={redTube}>
        <meshBasicMaterial ref={redMat} color={C.red} toneMapped={false} transparent opacity={0} blending={THREE.AdditiveBlending} depthWrite={false} />
      </mesh>
      <points ref={burst} geometry={burstGeom}>
        <pointsMaterial size={isMobile ? 0.12 : 0.1} color={C.red} transparent opacity={0} sizeAttenuation blending={THREE.AdditiveBlending} depthWrite={false} />
      </points>
    </group>
  );
}

export default React.memo(SLAClock);
