import assert from "node:assert/strict";
import { describe, it } from "node:test";
import * as THREE from "three";
import CALIFORNIA_CITY from "../cities/california.ts";
import { createFreewayWorld } from "../engine/structures.ts";
import type { World } from "../engine/world.ts";
import CALIFORNIA_TRANSPORT from "../transport/california.ts";
import { buildFreewayWorldPlan } from "../transport/freewayWorld.ts";

describe("freeway world v2", () => {
  it("compiles route identity and roadside placement deterministically", () => {
    const first = buildFreewayWorldPlan(CALIFORNIA_TRANSPORT, { seed: 115, sampleCount: 32 });
    const replay = buildFreewayWorldPlan(CALIFORNIA_TRANSPORT, { seed: 115, sampleCount: 32 });
    const alternate = buildFreewayWorldPlan(CALIFORNIA_TRANSPORT, { seed: 116, sampleCount: 32 });
    assert.deepEqual(first, replay);
    assert.notDeepEqual(first, alternate);
    assert.deepEqual(
      first.routes.map(({ routeId, identity, shield, character }) => ({ routeId, identity, shield, character })),
      [
        { routeId: "la-sf-us-101", identity: "us-highway", shield: "101", character: "coastal-oak" },
        { routeId: "la-sf-i-5", identity: "interstate", shield: "5", character: "central-valley" },
      ],
    );
    assert.ok(first.routes.every((route) => route.samples.length === 32));
    assert.ok(first.routes.flatMap((route) => route.samples).every((sample) =>
      sample.lanesPerDirection >= 2 && sample.lanesPerDirection <= 5 && Number.isFinite(sample.elevationPhase)
    ));
  });

  it("renders separated decks, markings, barriers, signs, and batched scenery", () => {
    const world = {
      city: CALIFORNIA_CITY,
      project(lat: number, lng: number): [number, number] {
        return [(lng + 121) * 20, -(lat - 36) * 20];
      },
      groundAt(): number {
        return 0;
      },
    } as unknown as World;
    const group = createFreewayWorld(world, CALIFORNIA_TRANSPORT);
    assert.equal(group.name, "freeway-world-v2");
    assert.equal(group.userData.planSeed, 101_005);
    const names: string[] = [];
    group.traverse((object) => names.push(object.name));
    assert.equal(names.filter((name) => name === "freeway:lane-dashes").length, 8);
    assert.equal(names.filter((name) => name === "freeway:median-barrier").length, 4);
    assert.equal(names.filter((name) => name === "freeway:outer-guardrail").length, 4);
    assert.ok(names.includes("freeway:sign:101"));
    assert.ok(names.includes("freeway:sign:5"));
    assert.ok(group.children.filter((child) => child instanceof THREE.InstancedMesh).length >= 7);
  });
});
