import * as THREE from "three";
import { seeded } from "./math";

/**
 * Deterministic route + delivery-node generation shared by RouteSystem and
 * VehicleFleet so glowing paths and moving vehicles stay perfectly aligned.
 */

export const HUB = new THREE.Vector3(0, 0.5, 0);
export const ROUTE_Y = 0.45;

export type RouteDef = {
  curve: THREE.CatmullRomCurve3;
  nodes: THREE.Vector3[];
};

export type SceneRoutes = {
  chaotic: RouteDef[];
  optimized: RouteDef[];
  chaosNodes: THREE.Vector3[];
  optimizedNodes: THREE.Vector3[];
};

function arc(points: THREE.Vector3[]): THREE.CatmullRomCurve3 {
  return new THREE.CatmullRomCurve3(points, false, "catmullrom", 0.5);
}

let cached: SceneRoutes | null = null;

export function buildRoutes(): SceneRoutes {
  if (cached) return cached;

  // --- Optimized clusters: 5 tidy zones around the hub --------------------
  const clusterCount = 5;
  const optimized: RouteDef[] = [];
  const optimizedNodes: THREE.Vector3[] = [];

  for (let c = 0; c < clusterCount; c++) {
    const baseAngle = (c / clusterCount) * Math.PI * 2 + 0.3;
    const radius = 7 + seeded(c * 7 + 1) * 3;
    const cx = Math.cos(baseAngle) * radius;
    const cz = Math.sin(baseAngle) * radius;

    // 2-3 stops per cluster (multi-trip planning)
    const stops = 2 + Math.floor(seeded(c * 7 + 2) * 2);
    const pts: THREE.Vector3[] = [HUB.clone()];
    // gentle lift-off control point
    pts.push(new THREE.Vector3(cx * 0.35, ROUTE_Y + 1.4, cz * 0.35));

    const nodes: THREE.Vector3[] = [];
    for (let s = 0; s < stops; s++) {
      const jx = (seeded(c * 31 + s * 5 + 3) - 0.5) * 3.2;
      const jz = (seeded(c * 31 + s * 5 + 4) - 0.5) * 3.2;
      const node = new THREE.Vector3(cx + jx, ROUTE_Y, cz + jz);
      nodes.push(node);
      optimizedNodes.push(node);
      pts.push(node.clone());
    }
    optimized.push({ curve: arc(pts), nodes });
  }

  // --- Chaotic routes: tangled, overlapping, wandering --------------------
  const chaotic: RouteDef[] = [];
  const chaosNodes: THREE.Vector3[] = [];
  const chaosCount = 6;

  for (let r = 0; r < chaosCount; r++) {
    const segs = 4 + Math.floor(seeded(r * 13 + 1) * 3);
    const pts: THREE.Vector3[] = [HUB.clone()];
    let angle = seeded(r * 13 + 2) * Math.PI * 2;
    const nodes: THREE.Vector3[] = [];
    for (let s = 0; s < segs; s++) {
      angle += (seeded(r * 13 + s * 3 + 3) - 0.5) * 2.6; // erratic turns
      const reach = 2.6 + seeded(r * 13 + s * 3 + 4) * 6.4; // tighter, more central
      const px = Math.cos(angle) * reach + (seeded(r * 17 + s) - 0.5) * 2.6;
      const pz = Math.sin(angle) * reach + (seeded(r * 19 + s) - 0.5) * 2.6;
      const py = ROUTE_Y + seeded(r * 23 + s) * 1.1;
      const p = new THREE.Vector3(px, py, pz);
      pts.push(p);
      if (s === segs - 1) {
        const node = new THREE.Vector3(px, ROUTE_Y, pz);
        chaosNodes.push(node);
        nodes.push(node);
      }
    }
    chaotic.push({ curve: arc(pts), nodes });
  }

  cached = { chaotic, optimized, chaosNodes, optimizedNodes };
  return cached;
}
