import { useRef } from "react";
import { useFrame } from "@react-three/fiber";
import * as THREE from "three";
import type { CombatState, CombatAction } from "./combatState";
import { orbitPosition } from "./combatMath";
import { SpaceCanvas } from "../shared/SpaceCanvas";
import { SpaceEnvironment } from "../shared/SpaceEnvironment";
import { ShipMesh } from "../shared/ShipMesh";
import { Projectiles } from "../shared/Projectiles";
import { RouteLine } from "../shared/RouteLine";
import type { Vec3 } from "../shared/types";

type CombatSceneProps = {
  state: CombatState;
  dispatch: React.Dispatch<CombatAction>;
};

function LockBrackets({ visible }: { visible: boolean }) {
  if (!visible) return null;
  return (
    <group>
      {[0, Math.PI / 2, Math.PI, Math.PI * 1.5].map((rot) => (
        <mesh key={rot} rotation={[0, 0, rot]} position={[0, 0, 0]}>
          <boxGeometry args={[0.25, 4, 0.06]} />
          <meshBasicMaterial color="#f0a030" />
        </mesh>
      ))}
    </group>
  );
}

function CombatWorld({ state, dispatch }: CombatSceneProps) {
  const playerRef = useRef<THREE.Group>(null);
  const enemyRef = useRef<THREE.Group>(null);
  const tickRef = useRef(0);
  const playerAngle = useRef(Math.PI);
  const enemyAngle = useRef(0);

  useFrame((_, dt) => {
    const elapsed = _.clock.elapsedTime;
    const afterburn = elapsed < state.afterburnUntil;
    const locked = state.lockState === "locked";
    const locking = state.lockState === "locking";

    if (locked || locking) {
      playerAngle.current += dt * (0.45 + state.power.engines * 0.12) * (afterburn ? 1.9 : 1);
      enemyAngle.current += dt * (0.42 * Math.max(0.15, state.enemy.engines / 100));
    }

    const playerRadius = locked ? 15 + state.power.engines * 2.2 : 14;
    const enemyRadius = locked || locking ? 15 * Math.max(0.2, state.enemy.engines / 100) : 0;
    const playerPos = locked
      ? orbitPosition(playerAngle.current, playerRadius, 4, 0.65, -2)
      : ([-16, Math.sin(elapsed * 1.3) * 0.6, 2] as Vec3);
    const enemyPos = locked || locking
      ? orbitPosition(enemyAngle.current, enemyRadius, 3, 0.7, 10)
      : ([18, Math.cos(elapsed * 1.1) * 0.5, -2] as Vec3);

    playerRef.current?.position.set(...playerPos);
    enemyRef.current?.position.set(...enemyPos);
    if (enemyRef.current && playerRef.current) {
      playerRef.current.lookAt(enemyRef.current.position);
      enemyRef.current.lookAt(playerRef.current.position);
    }

    tickRef.current += dt;
    while (tickRef.current >= 0.05) {
      tickRef.current -= 0.05;
      dispatch({ type: "tick", payload: { dt: 0.05, playerPosition: playerPos, enemyPosition: enemyPos, elapsed } });
    }
  });

  const playerPosition = (playerRef.current?.position.toArray() ?? [-16, 0, 2]) as Vec3;
  const enemyPosition = (enemyRef.current?.position.toArray() ?? [18, 0, -2]) as Vec3;

  return (
    <>
      <SpaceEnvironment density={2600} spread={1400} />
      <gridHelper args={[180, 18, "#0d1520", "#0d1520"]} position={[0, -4, 0]} />
      <group ref={playerRef}>
        <ShipMesh scale={0.55} engineActive hostile={false} />
        <mesh>
          <sphereGeometry args={[3.1 + state.power.shields * 0.18, 28, 28]} />
          <meshBasicMaterial color="#22d3ee" transparent opacity={0.03 + state.power.shields * 0.012} wireframe />
        </mesh>
      </group>
      <group ref={enemyRef}>
        <ShipMesh scale={0.46} color="#7f1d1d" emissive="#ef4444" hostile engineActive={state.enemy.engines > 8} />
        <LockBrackets visible={state.lockState !== "idle"} />
      </group>
      {state.lockState === "locked" && <RouteLine points={[playerPosition, enemyPosition]} color="#f0a030" width={1} />}
      <Projectiles projectiles={state.projectiles} impacts={state.impacts} />
    </>
  );
}

export function CombatScene(props: CombatSceneProps) {
  return (
    <SpaceCanvas camera={{ position: [0, 34, 62], fov: 55, near: 0.1, far: 3000 }}>
      <CombatWorld {...props} />
    </SpaceCanvas>
  );
}
