import * as THREE from 'three';

let scene, camera, renderer;
const _worldObjects = [];

export function initWorld(existingCanvas) {
  _worldObjects.length = 0;

  scene = new THREE.Scene();
  scene.background = new THREE.Color(0x080610);
  scene.fog = new THREE.FogExp2(0x080610, 0.038);

  camera = new THREE.PerspectiveCamera(58, window.innerWidth / window.innerHeight, 0.1, 200);
  camera.position.set(0, 7, 14);
  camera.lookAt(0, 2, -2);

  renderer = new THREE.WebGLRenderer({
    antialias: true,
    canvas: existingCanvas || undefined,
  });
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
  renderer.outputColorSpace = THREE.SRGBColorSpace;
  renderer.shadowMap.enabled = true;
  renderer.shadowMap.type = THREE.PCFSoftShadowMap;

  if (!existingCanvas) {
    document.body.prepend(renderer.domElement);
  }

  addLights(scene);
  buildRoom(scene);

  return { scene, camera, renderer };
}

function addLights(scene) {
  const ambient = new THREE.AmbientLight(0x0a2010, 0.45);
  scene.add(ambient);

  const fireplace = new THREE.PointLight(0xff7722, 4.5, 32);
  fireplace.position.set(-9, 3.5, 6);
  fireplace.castShadow = true;
  scene.add(fireplace);

  const candle = new THREE.PointLight(0xffcc77, 1.8, 8);
  candle.position.set(0.7, 1.9, -3.6);
  scene.add(candle);

  const fill = new THREE.DirectionalLight(0x001a00, 0.2);
  fill.position.set(0, 12, 8);
  scene.add(fill);
}

function buildRoom(scene) {
  const stoneMat = new THREE.MeshStandardMaterial({ color: 0x181820, roughness: 0.95, metalness: 0.0 });
  const woodMat = new THREE.MeshStandardMaterial({ color: 0x3d2506, roughness: 0.92 });

  const floor = new THREE.Mesh(new THREE.PlaneGeometry(28, 28), stoneMat.clone());
  floor.rotation.x = -Math.PI / 2;
  floor.receiveShadow = true;
  scene.add(floor);
  _worldObjects.push(floor);

  const grid = new THREE.GridHelper(28, 14, 0x28283a, 0x1c1c28);
  grid.position.y = 0.005;
  scene.add(grid);
  _worldObjects.push(grid);

  buildDesk(scene, woodMat);
  buildShelves(scene, woodMat);
  buildFireplaceGlow(scene);
}

function buildDesk(scene, woodMat) {
  const top = new THREE.Mesh(new THREE.BoxGeometry(2.8, 0.1, 1.3), woodMat.clone());
  top.position.set(0, 1.05, -4.1);
  top.castShadow = true;
  top.receiveShadow = true;
  scene.add(top);
  _worldObjects.push(top);

  const legGeo = new THREE.CylinderGeometry(0.055, 0.055, 1.05, 8);
  [[-1.25, -3.55], [1.25, -3.55], [-1.25, -4.65], [1.25, -4.65]].forEach(([x, z]) => {
    const leg = new THREE.Mesh(legGeo, woodMat.clone());
    leg.position.set(x, 0.525, z);
    leg.castShadow = true;
    scene.add(leg);
    _worldObjects.push(leg);
  });

  const scrollMat = new THREE.MeshStandardMaterial({ color: 0xe8d5a0, roughness: 1.0 });
  const scroll = new THREE.Mesh(new THREE.BoxGeometry(0.9, 0.02, 0.65), scrollMat);
  scroll.position.set(-0.65, 1.12, -4.1);
  scroll.rotation.y = 0.18;
  scene.add(scroll);
  _worldObjects.push(scroll);

  const scroll2 = new THREE.Mesh(new THREE.BoxGeometry(0.5, 0.015, 0.4), scrollMat.clone());
  scroll2.position.set(0.3, 1.12, -4.3);
  scroll2.rotation.y = -0.25;
  scene.add(scroll2);
  _worldObjects.push(scroll2);
}

function buildShelves(scene, woodMat) {
  const bookColors = [0x8b0000, 0x00008b, 0x004400, 0x6b3300, 0x440066, 0x884400, 0x005566, 0x663300];
  [2.6, 3.7, 4.8].forEach(y => {
    const shelf = new THREE.Mesh(new THREE.BoxGeometry(3.8, 0.07, 0.48), woodMat.clone());
    shelf.position.set(-8.5, y, -2.2);
    shelf.rotation.y = 0.12;
    shelf.castShadow = true;
    scene.add(shelf);
    _worldObjects.push(shelf);

    for (let i = 0; i < 7; i++) {
      const h = 0.38 + Math.random() * 0.22;
      const bookMat = new THREE.MeshStandardMaterial({ color: bookColors[i % bookColors.length], roughness: 0.95 });
      const book = new THREE.Mesh(new THREE.BoxGeometry(0.11, h, 0.34), bookMat);
      book.position.set(-10.0 + i * 0.43, y + h / 2 + 0.04, -2.2 + Math.random() * 0.04);
      book.rotation.y = 0.12 + (Math.random() - 0.5) * 0.08;
      scene.add(book);
      _worldObjects.push(book);
    }
  });
}

function buildFireplaceGlow(scene) {
  const glowMat = new THREE.MeshBasicMaterial({ color: 0xff5500, transparent: true, opacity: 0.1 });
  const glow = new THREE.Mesh(new THREE.PlaneGeometry(3.5, 3), glowMat);
  glow.position.set(-11.5, 2.5, 4);
  glow.rotation.y = Math.PI / 2;
  scene.add(glow);
  _worldObjects.push(glow);
}

export function disposeWorld(renderer, _scene) {
  for (const obj of _worldObjects) {
    if (obj.geometry) obj.geometry.dispose();
    if (obj.material) {
      const mats = Array.isArray(obj.material) ? obj.material : [obj.material];
      mats.forEach(m => { if (m.map) m.map.dispose(); m.dispose(); });
    }
  }
  _worldObjects.length = 0;
  renderer.dispose();
}

export function onWindowResize(camera, renderer) {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
}
