import { useMemo, useRef } from "react";
import { useFrame } from "@react-three/fiber";
import * as THREE from "three";
import { SpaceCanvas } from "../shared/SpaceCanvas";
import { SpaceEnvironment } from "../shared/SpaceEnvironment";
import { CameraRig } from "../shared/CameraRig";
import { ShipMesh } from "../shared/ShipMesh";
import { RouteLine } from "../shared/RouteLine";
import type { NavigationRoute, Vec3 } from "../shared/types";

type WarpBubbleSceneProps = {
  route: NavigationRoute | null;
  activeSegmentIndex: number;
  segmentProgress: number;
  totalProgress: number;
};

const routePoint = (index: number, count: number): Vec3 => {
  const offset = index - (count - 1) / 2;
  return [offset * 14, 14 + Math.sin(index * 0.9) * 3, -34];
};

function WarpWorld({ route, activeSegmentIndex, segmentProgress, totalProgress }: WarpBubbleSceneProps) {
  const tunnelRef = useRef<THREE.Group>(null);
  const shipRef = useRef<THREE.Group>(null);
  const streaks = useMemo(() => Array.from({ length: 88 }, (_, index) => {
    const angle = index * 2.399;
    const radius = 12 + (index % 9) * 2.1;
    return {
      id: index,
      x: Math.cos(angle) * radius,
      y: Math.sin(angle) * radius,
      z: -90 + (index % 22) * 8,
      length: 12 + (index % 5) * 6,
      color: index % 4 === 0 ? "#f0a030" : "#22d3ee",
    };
  }), []);

  useFrame((state, dt) => {
    if (tunnelRef.current) {
      tunnelRef.current.rotation.z += dt * 0.35;
      tunnelRef.current.children.forEach((child, index) => {
        child.position.z += dt * (42 + (index % 7) * 5);
        if (child.position.z > 28) child.position.z = -120;
      });
    }
    if (shipRef.current) {
      shipRef.current.rotation.z = Math.sin(state.clock.elapsedTime * 1.7) * 0.035;
      shipRef.current.position.y = Math.sin(state.clock.elapsedTime * 2.2) * 0.2;
    }
  });

  const routePoints = route?.systems.map((_, index) => routePoint(index, route.systems.length)) ?? [];
  const active = route?.segments[activeSegmentIndex] ?? null;

  return (
    <>
      <SpaceEnvironment density={2600} spread={1500} />
      <CameraRig target={[0, 0, -18]} />
      <ambientLight intensity={0.85} />
      <pointLight position={[0, 12, 18]} color="#22d3ee" intensity={3} distance={120} />
      <group ref={tunnelRef}>
        {streaks.map((streak) => (
          <mesh key={streak.id} position={[streak.x, streak.y, streak.z]} rotation={[Math.PI / 2, 0, 0]}>
            <cylinderGeometry args={[0.045, 0.045, streak.length, 6]} />
            <meshBasicMaterial color={streak.color} transparent opacity={0.68} />
          </mesh>
        ))}
      </group>
      <mesh position={[0, 0, -12]}>
        <sphereGeometry args={[18 + Math.sin(totalProgress * Math.PI) * 2, 48, 24]} />
        <meshBasicMaterial color="#22d3ee" wireframe transparent opacity={0.16} />
      </mesh>
      <mesh position={[0, 0, -12]}>
        <sphereGeometry args={[10 + segmentProgress * 4, 32, 16]} />
        <meshBasicMaterial color="#f0a030" wireframe transparent opacity={0.12} />
      </mesh>
      <group ref={shipRef} rotation={[0, -Math.PI / 2, 0]}>
        <ShipMesh scale={0.58} engineActive />
      </group>
      {routePoints.length > 1 && <RouteLine points={routePoints} color="#22d3ee" width={2} />}
      {routePoints.map((point, index) => (
        <mesh key={`${route?.systems[index]?.id ?? index}-warp-node`} position={point}>
          <sphereGeometry args={[index === activeSegmentIndex || index === activeSegmentIndex + 1 ? 0.9 : 0.55, 16, 16]} />
          <meshBasicMaterial color={index <= activeSegmentIndex ? "#f0a030" : "#22d3ee"} transparent opacity={0.9} />
        </mesh>
      ))}
      {active && (
        <group position={[0, -12, -26]}>
          <mesh position={[-18 + segmentProgress * 36, 0, 0]}>
            <sphereGeometry args={[0.9, 16, 16]} />
            <meshBasicMaterial color="#f0a030" />
          </mesh>
          <RouteLine points={[[-18, 0, 0], [18, 0, 0]]} color="#f0a030" width={3} />
        </group>
      )}
    </>
  );
}

export function WarpBubbleScene(props: WarpBubbleSceneProps) {
  return (
    <SpaceCanvas camera={{ position: [0, 8, 42], fov: 62, near: 0.1, far: 5000 }}>
      <WarpWorld {...props} />
    </SpaceCanvas>
  );
}
