import * as THREE from "three";

/**
 * Herodian clay oil lamp — procedural blockout inspired by common 1st-century CE
 * archaeological forms (oval body, pinched nozzle, central fill hole).
 *
 * Reference (public domain): Wikimedia Commons category "Herodian oil lamps"
 * https://commons.wikimedia.org/wiki/Category:Herodian_oil_lamps
 * Example artifact photo: https://commons.wikimedia.org/wiki/File:Herodian_oil_lamp.jpg
 * (Israel Antiquities Authority / CC BY-SA — silhouette used for proportions only;
 *  this model is code-only primitives, not a mesh download.)
 *
 * img2threejs-style factory: returns a named THREE.Group ready to mount in a scene.
 */

export interface HerodianOilLampOptions {
  /** Overall scale multiplier (default 1). */
  scale?: number;
  /** Enable cast/receive shadows on lamp meshes (default true). */
  shadows?: boolean;
}

/** Warm terracotta palette sampled from typical Herodian lamp clay. */
const CLAY_BODY = 0xb56a3c;
const CLAY_SHADOW = 0x7a4224;
const CLAY_HIGHLIGHT = 0xd4925a;
const WICK_CHAR = 0x1a1410;
const SOOT = 0x2b2118;

function clayMaterial(color: number, roughness = 0.88): THREE.MeshStandardMaterial {
  return new THREE.MeshStandardMaterial({
    color,
    roughness,
    metalness: 0.02,
    flatShading: true,
  });
}

function addMesh(
  parent: THREE.Object3D,
  geometry: THREE.BufferGeometry,
  material: THREE.Material,
  position: THREE.Vector3Like,
  rotation: THREE.EulerLike = new THREE.Euler(),
  scale: THREE.Vector3Like = new THREE.Vector3(1, 1, 1),
  shadows = true,
): THREE.Mesh {
  const mesh = new THREE.Mesh(geometry, material);
  mesh.position.copy(position as THREE.Vector3);
  mesh.rotation.copy(rotation as THREE.Euler);
  mesh.scale.copy(scale as THREE.Vector3);
  mesh.castShadow = shadows;
  mesh.receiveShadow = shadows;
  parent.add(mesh);
  return mesh;
}

/**
 * Build a Herodian oil-lamp THREE.Group (body, nozzle, fill hole, wick channel).
 */
export function createHerodianOilLampModel(
  options: HerodianOilLampOptions = {},
): THREE.Group {
  const scale = options.scale ?? 1;
  const shadows = options.shadows ?? true;

  const root = new THREE.Group();
  root.name = "HerodianOilLamp";
  root.scale.setScalar(scale);

  const bodyMat = clayMaterial(CLAY_BODY);
  const rimMat = clayMaterial(CLAY_HIGHLIGHT, 0.82);
  const shadowMat = clayMaterial(CLAY_SHADOW, 0.95);

  // Oval lamp body — flattened sphere stretched along X (length) and Z (width).
  const body = addMesh(
    root,
    new THREE.SphereGeometry(1, 24, 16),
    bodyMat,
    new THREE.Vector3(0, 0.08, 0),
    new THREE.Euler(0, 0, 0),
    new THREE.Vector3(1.35, 0.42, 1.05),
    shadows,
  );
  body.name = "body";

  // Raised shoulder ring around the fill hole.
  addMesh(
    root,
    new THREE.TorusGeometry(0.22, 0.045, 10, 24),
    rimMat,
    new THREE.Vector3(-0.05, 0.38, 0),
    new THREE.Euler(Math.PI / 2, 0, 0),
    new THREE.Vector3(1, 1, 1),
    shadows,
  );

  // Central fill hole (recessed dark disc).
  addMesh(
    root,
    new THREE.CylinderGeometry(0.16, 0.18, 0.12, 20),
    shadowMat,
    new THREE.Vector3(-0.05, 0.34, 0),
    new THREE.Euler(0, 0, 0),
    new THREE.Vector3(1, 1, 1),
    shadows,
  );

  // Nozzle bridge — pinch that carries oil to the wick.
  addMesh(
    root,
    new THREE.BoxGeometry(0.55, 0.18, 0.38),
    bodyMat,
    new THREE.Vector3(0.95, 0.12, 0),
    new THREE.Euler(0, 0, -0.08),
    new THREE.Vector3(1, 1, 1),
    shadows,
  );

  // Tapered spout / nozzle tip.
  addMesh(
    root,
    new THREE.ConeGeometry(0.2, 0.55, 16),
    bodyMat,
    new THREE.Vector3(1.45, 0.1, 0),
    new THREE.Euler(0, 0, -Math.PI / 2),
    new THREE.Vector3(1, 0.85, 0.75),
    shadows,
  );

  // Wick channel groove along the nozzle top.
  addMesh(
    root,
    new THREE.BoxGeometry(0.7, 0.04, 0.12),
    shadowMat,
    new THREE.Vector3(1.05, 0.22, 0),
    new THREE.Euler(0, 0, -0.06),
    new THREE.Vector3(1, 1, 1),
    shadows,
  );

  // Burnt wick stub at the nozzle mouth.
  addMesh(
    root,
    new THREE.CylinderGeometry(0.035, 0.05, 0.12, 10),
    new THREE.MeshStandardMaterial({
      color: WICK_CHAR,
      roughness: 1,
      metalness: 0,
      flatShading: true,
    }),
    new THREE.Vector3(1.72, 0.18, 0),
    new THREE.Euler(0, 0, -0.35),
    new THREE.Vector3(1, 1, 1),
    shadows,
  );

  // Soot stain where flame meets clay.
  addMesh(
    root,
    new THREE.SphereGeometry(0.12, 10, 8),
    new THREE.MeshStandardMaterial({
      color: SOOT,
      roughness: 1,
      metalness: 0,
      transparent: true,
      opacity: 0.75,
      flatShading: true,
    }),
    new THREE.Vector3(1.68, 0.24, 0),
    new THREE.Euler(0, 0, 0),
    new THREE.Vector3(0.9, 0.5, 0.7),
    false,
  );

  // Rear finger lug common on Herodian lamps.
  addMesh(
    root,
    new THREE.BoxGeometry(0.18, 0.28, 0.22),
    rimMat,
    new THREE.Vector3(-1.05, 0.18, 0),
    new THREE.Euler(0, 0, 0.25),
    new THREE.Vector3(1, 1, 1),
    shadows,
  );

  // Base contact patch — flattens the resting pose on a table plane (y = 0).
  root.position.y = 0.02;

  root.userData.sculptRuntime = {
    kind: "object",
    subject: "herodian-oil-lamp",
    reference:
      "https://commons.wikimedia.org/wiki/Category:Herodian_oil_lamps",
    nodes: {
      body: body,
      root,
    },
  };

  return root;
}
