import * as THREE from 'three';
import { loadGLB } from './MeshLoader';

let crossGeometry: THREE.BufferGeometry | null = null;
let crossParticlesTemplate: THREE.Points | null = null;

export async function initCrossModel() {
  try {
    const gltf = await loadGLB('cross');
    gltf.scene.traverse((child) => {
      if (child instanceof THREE.Mesh) {
        crossGeometry = child.geometry;
      }
    });
  } catch {
    console.warn('Failed to load cross model');
  }
}

function createGreenParticles(): THREE.Points {
  const count = 50;
  const tex = new THREE.TextureLoader().load('./textures/flame.png');
  tex.colorSpace = THREE.SRGBColorSpace;
  const geom = new THREE.BufferGeometry();
  const positions = new Float32Array(count * 3);
  geom.setAttribute('position', new THREE.BufferAttribute(positions, 3));
  const mat = new THREE.PointsMaterial({
    map: tex,
    color: 0x66ff66,
    size: 0.12,
    blending: THREE.AdditiveBlending,
    depthWrite: false,
    transparent: true,
  });
  const points = new THREE.Points(geom, mat);
  points.renderOrder = 999;
  points.userData = {
    velocities: [] as THREE.Vector3[],
    lifetimes: [] as number[],
    ages: [] as number[],
    timer: 0,
  };
  for (let i = 0; i < count; i++) {
    positions[i * 3] = (Math.random() - 0.5) * 0.8;
    positions[i * 3 + 1] = Math.random() * 1.2;
    positions[i * 3 + 2] = (Math.random() - 0.5) * 0.8;
    points.userData.velocities.push(new THREE.Vector3(
      (Math.random() - 0.5) * 0.5,
      1.5 + Math.random() * 1.5,
      (Math.random() - 0.5) * 0.5
    ));
    points.userData.lifetimes.push(1 + Math.random());
    points.userData.ages.push(Math.random() * 2);
  }
  return points;
}

export class Cross {
  body: THREE.Group;
  private particles: THREE.Points;

  constructor(position: THREE.Vector3) {
    this.body = new THREE.Group();
    this.body.position.copy(position);
    this.body.position.y = 0.3;

    if (crossGeometry) {
      // Original material: red cross (from j3o material extraction)
      const mesh = new THREE.Mesh(crossGeometry, new THREE.MeshToonMaterial({
        color: 0xff0000, emissive: 0x440000,
      }));
      mesh.castShadow = true;
      mesh.scale.set(0.25, 0.25, 0.25);
      this.body.add(mesh);
    } else {
      // Fallback cross
      const crossMaterial = new THREE.MeshToonMaterial({
        color: 0xff0000, emissive: 0x440000,
      });
      const vertical = new THREE.Mesh(new THREE.BoxGeometry(0.15, 0.8, 0.15), crossMaterial);
      vertical.position.y = 0.4;
      this.body.add(vertical);
      const horizontal = new THREE.Mesh(new THREE.BoxGeometry(0.6, 0.15, 0.15), crossMaterial);
      horizontal.position.y = 0.5;
      this.body.add(horizontal);
    }

    // Green glow
    const glowGeom = new THREE.SphereGeometry(0.6, 16, 16);
    const glowMat = new THREE.MeshBasicMaterial({
      color: 0x00ff00, transparent: true, opacity: 0.15,
    });
    const glow = new THREE.Mesh(glowGeom, glowMat);
    this.body.add(glow);

    // Upward-flying light green particles (like the original)
    this.particles = createGreenParticles();
    this.body.add(this.particles);
  }

  update(dt: number) {
    const attr = this.particles.geometry.getAttribute('position') as THREE.BufferAttribute;
    const arr = attr.array as Float32Array;
    const ud = this.particles.userData;
    const count = ud.velocities.length;

    for (let i = 0; i < count; i++) {
      ud.ages[i] += dt;
      const life = ud.lifetimes[i];
      if (ud.ages[i] >= life) {
        // Respawn at bottom
        ud.ages[i] = 0;
        arr[i * 3] = (Math.random() - 0.5) * 0.8;
        arr[i * 3 + 1] = 0;
        arr[i * 3 + 2] = (Math.random() - 0.5) * 0.8;
        continue;
      }
      const v = ud.velocities[i];
      arr[i * 3] += v.x * dt;
      arr[i * 3 + 1] += v.y * dt;
      arr[i * 3 + 2] += v.z * dt;
    }
    attr.needsUpdate = true;
  }
}
