import * as THREE from 'three';
import type { Game } from './Game';
import { auraRadius, auraDamage, auraPush } from './Skills';

const TICK = 0.5;

export class Aura {
  private group: THREE.Group;
  private fill: THREE.Mesh;
  private ring: THREE.Mesh;
  private tickTimer = 0;
  private pulse = 0;

  constructor(scene: THREE.Scene) {
    this.group = new THREE.Group();

    this.fill = new THREE.Mesh(
      new THREE.CircleGeometry(1, 48),
      new THREE.MeshBasicMaterial({
        color: 0x66ccff,
        transparent: true,
        opacity: 0.12,
        depthWrite: false,
      })
    );
    this.fill.rotation.x = -Math.PI / 2;
    this.fill.position.y = 0.05;
    this.fill.renderOrder = 998;
    this.group.add(this.fill);

    this.ring = new THREE.Mesh(
      new THREE.RingGeometry(0.93, 1, 48),
      new THREE.MeshBasicMaterial({
        color: 0x88ddff,
        transparent: true,
        opacity: 0.5,
        side: THREE.DoubleSide,
        depthWrite: false,
      })
    );
    this.ring.rotation.x = -Math.PI / 2;
    this.ring.position.y = 0.06;
    this.ring.renderOrder = 999;
    this.group.add(this.ring);

    scene.add(this.group);
  }

  update(dt: number, game: Game) {
    const level = game.skillSystem.getLevel('aura');
    if (level <= 0) return;

    const radius = auraRadius(level);
    this.group.position.x = game.player.body.position.x;
    this.group.position.z = game.player.body.position.z;
    this.group.scale.setScalar(radius);

    if (this.pulse > 0) {
      this.pulse -= dt * 2.5;
      const p = Math.max(0, this.pulse);
      const s = 1 + p * 0.12;
      this.fill.scale.setScalar(s);
      this.ring.scale.setScalar(s);
      (this.ring.material as THREE.MeshBasicMaterial).opacity = 0.5 + p * 0.4;
    }

    this.tickTimer -= dt;
    if (this.tickTimer > 0) return;
    this.tickTimer = TICK;

    const damage = auraDamage(level);
    const push = auraPush(level);
    const center = game.player.body.position;
    for (const enemy of game.enemies) {
      if (enemy.dead) continue;
      const dist = enemy.body.position.distanceTo(center);
      if (dist > radius + 0.4) continue;
      enemy.takeDamage(damage, game, false, center);
      // Stationaere Gegner (Bosse, Tuerme) werden nur geschaedigt, nicht geschoben
      if (enemy.immovable) continue;
      const dir = new THREE.Vector3()
        .subVectors(enemy.body.position, center);
      dir.y = 0;
      if (dir.lengthSq() < 0.01) {
        dir.set(Math.random() - 0.5, 0, Math.random() - 0.5);
      }
      dir.normalize();
      enemy.body.position.addScaledVector(dir, push);
      game.clampToArena(enemy.body.position);
    }
    this.pulse = 1;
  }

  dispose(scene: THREE.Scene) {
    scene.remove(this.group);
    this.fill.geometry.dispose();
    (this.fill.material as THREE.Material).dispose();
    this.ring.geometry.dispose();
    (this.ring.material as THREE.Material).dispose();
  }
}
