import * as THREE from 'three';

const MATS = () => ({
  hull: new THREE.MeshStandardMaterial({ color: 0xd7dde6, roughness: 0.42, metalness: 0.85 }),
  hull2: new THREE.MeshStandardMaterial({ color: 0x8a94a6, roughness: 0.55, metalness: 0.8 }),
  trim: new THREE.MeshStandardMaterial({ color: 0xff7a3d, roughness: 0.4, metalness: 0.6,
    emissive: 0xff5a1a, emissiveIntensity: 0.45 }),
  glass: new THREE.MeshPhysicalMaterial({ color: 0x123244, roughness: 0.08, metalness: 0.1,
    transmission: 0.0, transparent: true, opacity: 0.72, clearcoat: 1, clearcoatRoughness: 0.05,
    emissive: 0x0a2030, emissiveIntensity: 0.3 }),
  engine: new THREE.MeshStandardMaterial({ color: 0x55f0ff, emissive: 0x46f0e6, emissiveIntensity: 2.4,
    roughness: 0.3, metalness: 0.4 }),
  dark: new THREE.MeshStandardMaterial({ color: 0x2a2f38, roughness: 0.7, metalness: 0.6 }),
});

// Build a sleek explorer ship. Faces -Z (forward).
export function createShip() {
  const g = new THREE.Group();
  g.name = 'ship';
  const m = MATS();

  // fuselage: tapered, two segments
  const body = new THREE.Mesh(new THREE.CylinderGeometry(0.55, 0.95, 4.2, 14), m.hull);
  body.rotation.x = Math.PI / 2;
  body.scale.set(1, 1, 1.0);
  body.name = 'fuselage';
  g.add(body);

  const nose = new THREE.Mesh(new THREE.ConeGeometry(0.55, 1.8, 14), m.hull);
  nose.rotation.x = -Math.PI / 2;
  nose.position.z = -3.0;
  g.add(nose);

  const tail = new THREE.Mesh(new THREE.CylinderGeometry(0.95, 0.6, 1.0, 14), m.hull2);
  tail.rotation.x = Math.PI / 2;
  tail.position.z = 2.4;
  g.add(tail);

  // belly spine
  const spine = new THREE.Mesh(new THREE.BoxGeometry(0.5, 0.35, 4.6), m.hull2);
  spine.position.set(0, -0.55, 0.2);
  g.add(spine);

  // cockpit canopy
  const canopy = new THREE.Mesh(new THREE.SphereGeometry(0.6, 20, 14, 0, Math.PI * 2, 0, Math.PI * 0.62), m.glass);
  canopy.scale.set(1, 0.8, 1.5);
  canopy.position.set(0, 0.42, -1.1);
  canopy.name = 'canopy';
  g.add(canopy);

  // wings (swept, angled down)
  const wingShape = new THREE.BoxGeometry(3.4, 0.12, 1.5);
  for (const s of [-1, 1]) {
    const wing = new THREE.Mesh(wingShape, m.hull);
    wing.position.set(s * 1.9, -0.1, 0.7);
    wing.rotation.z = s * 0.18;
    wing.rotation.y = s * 0.35;
    g.add(wing);
    // wingtip trim light
    const tip = new THREE.Mesh(new THREE.BoxGeometry(0.5, 0.16, 0.5), m.trim);
    tip.position.set(s * 3.4, -0.05, 1.0);
    g.add(tip);
    // engine nacelle under each wing
    const nac = new THREE.Mesh(new THREE.CylinderGeometry(0.3, 0.34, 1.6, 12), m.dark);
    nac.rotation.x = Math.PI / 2;
    nac.position.set(s * 1.7, -0.25, 1.5);
    g.add(nac);
    const glow = new THREE.Mesh(new THREE.CylinderGeometry(0.26, 0.12, 0.5, 12), m.engine);
    glow.rotation.x = Math.PI / 2;
    glow.position.set(s * 1.7, -0.25, 2.5);
    glow.name = 'engine' + s;
    g.add(glow);
  }
  // central main engine
  const mainGlow = new THREE.Mesh(new THREE.CylinderGeometry(0.4, 0.18, 0.6, 16), m.engine);
  mainGlow.rotation.x = Math.PI / 2;
  mainGlow.position.set(0, 0, 3.0);
  mainGlow.name = 'engineMain';
  g.add(mainGlow);

  // dorsal fin
  const fin = new THREE.Mesh(new THREE.BoxGeometry(0.14, 1.1, 1.4), m.hull2);
  fin.position.set(0, 0.6, 1.8);
  fin.rotation.x = 0.3;
  g.add(fin);

  // trim strips along body
  for (const s of [-1, 1]) {
    const strip = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.12, 3.4), m.trim);
    strip.position.set(s * 0.5, 0.2, 0);
    g.add(strip);
  }

  g.userData.engines = [g.getObjectByName('engineMain'), g.getObjectByName('engine-1'), g.getObjectByName('engine1')].filter(Boolean);
  g.userData.engineMat = m.engine;
  g.userData.mats = m;
  return g;
}

// Parked surface version: ship + landing struts, slight tilt.
export function createParkedShip() {
  const g = new THREE.Group();
  const ship = createShip();
  g.add(ship);
  const m = ship.userData.mats;
  for (const sx of [-1, 1]) {
    for (const sz of [-1, 1]) {
      const strut = new THREE.Mesh(new THREE.CylinderGeometry(0.08, 0.08, 1.4, 6), m.dark);
      strut.position.set(sx * 1.3, -1.0, sz * 1.2);
      strut.rotation.z = sx * 0.25;
      g.add(strut);
      const foot = new THREE.Mesh(new THREE.CylinderGeometry(0.25, 0.3, 0.18, 8), m.dark);
      foot.position.set(sx * 1.55, -1.7, sz * 1.2);
      g.add(foot);
    }
  }
  g.userData.ship = ship;
  return g;
}

// Arcade flight controller for space mode. Ship faces -Z.
export class ShipController {
  constructor(ship) {
    this.ship = ship;
    this.yaw = 0; this.pitch = 0; this.roll = 0;
    this.curSpeed = 0;
    this.boosting = false;
    this.baseSpeed = 70;
    this.boostSpeed = 220;
    this.tmpQ = new THREE.Quaternion();
    this.forward = new THREE.Vector3();
  }

  update(dt, input) {
    const sens = 0.0022;
    // accumulate yaw/pitch from mouse deltas
    this.yaw -= input.mouseDX * sens;
    this.pitch -= input.mouseDY * sens;
    this.pitch = Math.max(-1.2, Math.min(1.2, this.pitch));
    // bank into turns
    const targetRoll = -input.mouseDX * sens * 9;
    this.roll += (targetRoll - this.roll) * Math.min(1, dt * 6);

    const e = new THREE.Euler(this.pitch, this.yaw, this.roll, 'YXZ');
    this.ship.quaternion.setFromEuler(e);

    this.boosting = input.boost && input.thrust;
    const target = input.thrust ? (this.boosting ? this.boostSpeed : this.baseSpeed) : this.baseSpeed * 0.12;
    this.curSpeed += (target - this.curSpeed) * Math.min(1, dt * (this.boosting ? 1.6 : 2.4));

    this.forward.set(0, 0, -1).applyQuaternion(this.ship.quaternion);
    this.ship.position.addScaledVector(this.forward, this.curSpeed * dt);

    // engine glow reacts to speed
    const intensity = 1.6 + (this.curSpeed / this.boostSpeed) * 4.5 + (this.boosting ? 2 : 0);
    this.ship.userData.engineMat.emissiveIntensity = intensity;
    const sc = 0.8 + (this.curSpeed / this.boostSpeed) * 0.8 + (this.boosting ? 0.5 : 0);
    for (const eng of this.ship.userData.engines) eng.scale.z = sc;

    return this.curSpeed;
  }
}
