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

const ORBIT_RADIUS = 2.8;
const ORBIT_HEIGHT = 0.9;
const ORBIT_SPEED = 2.4;
const SPIN_SPEED = 14;
const HIT_CD = 0.6;
const HIT_RADIUS = 0.9;

export class Boomerang {
  private meshes: THREE.Mesh[] = [];
  private angle = 0;
  private hitTimers = new Map<Enemy, number>();

  constructor(scene: THREE.Scene) {
    const shape = new THREE.Shape();
    // Dünner Sichel-Bumerang: Bogen (~120° = 1/3 Kreis) mit schmaler Bahn
    const outer = 0.75;
    const inner = 0.47;
    const half = (60 * Math.PI) / 180;
    const capR = (outer - inner) / 2;
    const mid = (outer + inner) / 2;

    shape.moveTo(outer * Math.cos(-half), outer * Math.sin(-half));
    shape.absarc(0, 0, outer, -half, half, false);
    shape.absarc(
      mid * Math.cos(half), mid * Math.sin(half),
      capR, half, half + Math.PI, false
    );
    shape.absarc(0, 0, inner, half, -half, true);
    shape.absarc(
      mid * Math.cos(-half), mid * Math.sin(-half),
      capR, -half + Math.PI, -half, false
    );
    shape.closePath();
    const geom = new THREE.ExtrudeGeometry(shape, {
      depth: 0.06,
      bevelEnabled: true,
      bevelThickness: 0.02,
      bevelSize: 0.02,
      bevelSegments: 2,
    });
    geom.center();
    const mat = new THREE.MeshToonMaterial({ color: 0xc98a3d });

    for (let i = 0; i < 3; i++) {
      const mesh = new THREE.Mesh(geom, mat);
      mesh.rotation.x = -Math.PI / 2;
      mesh.castShadow = true;
      mesh.visible = false;
      scene.add(mesh);
      this.meshes.push(mesh);
    }
  }

  setLevel(level: number) {
    const count = level > 0 ? boomerangCount(level) : 0;
    for (let i = 0; i < this.meshes.length; i++) {
      this.meshes[i].visible = i < count;
    }
  }

  update(dt: number, game: Game) {
    const level = game.skillSystem.getLevel('boomerang');
    if (level <= 0) return;
    const count = boomerangCount(level);
    const damage = boomerangDamage(level);

    this.angle += ORBIT_SPEED * dt;
    const center = game.player.body.position;

    for (const [enemy, t] of this.hitTimers) {
      this.hitTimers.set(enemy, t - dt);
    }

    for (let i = 0; i < count; i++) {
      const mesh = this.meshes[i];
      const a = this.angle + (i / count) * Math.PI * 2;
      mesh.position.set(
        center.x + Math.cos(a) * ORBIT_RADIUS,
        ORBIT_HEIGHT + Math.sin(this.angle * 2 + i) * 0.15,
        center.z + Math.sin(a) * ORBIT_RADIUS
      );
      mesh.rotation.z += SPIN_SPEED * dt;

      for (const enemy of game.enemies) {
        if (enemy.dead) continue;
        const timer = this.hitTimers.get(enemy) ?? 0;
        if (timer > 0) continue;
        const dist = enemy.body.position.distanceTo(mesh.position);
        if (dist < HIT_RADIUS + 0.5) {
          this.hitTimers.set(enemy, HIT_CD);
          enemy.takeDamage(damage, game, true, mesh.position);
        }
      }
    }
  }

  dispose(scene: THREE.Scene) {
    for (const mesh of this.meshes) {
      scene.remove(mesh);
      mesh.geometry.dispose();
      (mesh.material as THREE.Material).dispose();
    }
    this.meshes = [];
  }
}
