import * as THREE from 'three';
import type { Game } from './Game';
import type { Enemy } from './Enemy';
import { trapDamage, trapHold } from './Skills';

const TRIGGER_RADIUS = 1.1;
const LIFETIME = 20;
const TICK = 0.5;

export class Trap {
  body: THREE.Group;
  private level: number;
  private life = LIFETIME;
  private triggered = false;
  private tickTimer = 0;
  private target: Enemy | null = null;
  private jaws: THREE.Mesh[];
  private pulse = 0;

  constructor(position: THREE.Vector3, level: number) {
    this.level = level;
    this.body = new THREE.Group();
    this.body.position.copy(position);
    this.body.position.y = 0;

    const baseGeom = new THREE.CylinderGeometry(0.45, 0.55, 0.12, 24);
    const baseMat = new THREE.MeshToonMaterial({ color: 0x556066 });
    const base = new THREE.Mesh(baseGeom, baseMat);
    base.position.y = 0.06;
    base.castShadow = true;
    this.body.add(base);

    const ringGeom = new THREE.TorusGeometry(0.35, 0.05, 8, 24);
    const ringMat = new THREE.MeshBasicMaterial({
      color: 0xffcc33,
      transparent: true,
      opacity: 0.8,
    });
    const ring = new THREE.Mesh(ringGeom, ringMat);
    ring.rotation.x = -Math.PI / 2;
    ring.position.y = 0.13;
    this.body.add(ring);

    this.jaws = [];
    for (const side of [-1, 1]) {
      const jaw = new THREE.Mesh(
        new THREE.BoxGeometry(0.3, 0.06, 0.55),
        new THREE.MeshToonMaterial({ color: 0x9aa7b0 })
      );
      jaw.position.set(side * 0.2, 0.14, 0);
      jaw.castShadow = true;
      this.body.add(jaw);
      this.jaws.push(jaw);
    }
  }

  update(dt: number, game: Game): boolean {
    if (!this.triggered) {
      this.life -= dt;
      if (this.life <= 0) return false;

      for (const enemy of game.enemies) {
        if (enemy.dead) continue;
        const dist = enemy.body.position.distanceTo(this.body.position);
        if (dist < TRIGGER_RADIUS) {
          this.triggered = true;
          this.target = enemy;
          enemy.rootTime = trapHold(this.level);
          this.pulse = 1;
          break;
        }
      }
      return true;
    }

    this.tickTimer -= dt;
    if (this.pulse > 0) {
      this.pulse -= dt * 4;
      for (const jaw of this.jaws) {
        jaw.scale.setScalar(1 + Math.max(0, this.pulse) * 0.6);
      }
    }

    if (!this.target || this.target.dead || this.target.rootTime <= 0) {
      return false;
    }
    if (this.tickTimer <= 0) {
      this.tickTimer = TICK;
      this.target.takeDamage(
        (trapDamage(this.level) / trapHold(this.level)) * TICK,
        game,
        false,
        this.body.position
      );
    }
    return true;
  }

  dispose() {
    this.body.removeFromParent();
    for (const child of [...this.body.children]) {
      if (child instanceof THREE.Mesh) {
        child.geometry.dispose();
        (child.material as THREE.Material).dispose();
      }
    }
  }
}
