import * as THREE from 'three';
import type { Game } from './Game';

const ROOT_DURATION = 0.35;
const ROOT_TICK = 1.0;
const ROOT_COOLDOWN = 1.0;
const FADE_TIME = 0.6;

export class WebPatch {
  body: THREE.Group;
  private radius: number;
  private life: number;
  private rootTick = 0;
  private meshes: THREE.Mesh[] = [];

  constructor(position: THREE.Vector3, radius = 3, duration = 6) {
    this.radius = radius;
    this.life = duration;
    this.body = new THREE.Group();
    this.body.position.set(position.x, 0.08, position.z);

    const mat = new THREE.MeshToonMaterial({
      color: 0xdfe6ff,
      transparent: true,
      opacity: 0.55,
      depthWrite: false,
    });

    const disc = new THREE.Mesh(new THREE.CircleGeometry(radius, 24), mat);
    disc.rotation.x = -Math.PI / 2;
    disc.position.y = 0.01;
    this.body.add(disc);
    this.meshes.push(disc);

    // Radiale Fäden
    const threadMat = new THREE.MeshToonMaterial({
      color: 0xffffff,
      transparent: true,
      opacity: 0.7,
      depthWrite: false,
    });
    for (let i = 0; i < 8; i++) {
      const a = (i / 8) * Math.PI * 2;
      const thread = new THREE.Mesh(
        new THREE.BoxGeometry(radius * 2, 0.03, 0.05),
        threadMat
      );
      thread.rotation.y = -a;
      thread.position.y = 0.02;
      this.body.add(thread);
      this.meshes.push(thread);
    }

    // Konzentrische Ringe
    for (let r = 1; r <= 3; r++) {
      const ring = new THREE.Mesh(
        new THREE.RingGeometry(r * radius / 4 - 0.04, r * radius / 4 + 0.04, 24),
        threadMat
      );
      ring.rotation.x = -Math.PI / 2;
      ring.position.y = 0.025;
      this.body.add(ring);
      this.meshes.push(ring);
    }
  }

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

    const fade = Math.min(1, this.life / FADE_TIME);
    for (const mesh of this.meshes) {
      (mesh.material as THREE.MeshToonMaterial).opacity =
        (mesh === this.meshes[0] ? 0.55 : 0.7) * fade;
    }

    if (game.player.health > 0) {
      const dist = Math.hypot(
        game.player.body.position.x - this.body.position.x,
        game.player.body.position.z - this.body.position.z
      );
      if (dist < this.radius) {
        // Gepulste Fessel: kurzer Root, dann Lücke zum Rauslaufen.
        // rootCooldown verhindert Endlos-Fessel durch überlappende Netze.
        this.rootTick -= dt;
        if (this.rootTick <= 0 && game.player.rootCooldown <= 0) {
          game.player.rootTime = ROOT_DURATION;
          game.player.rootCooldown = ROOT_COOLDOWN;
          this.rootTick = ROOT_TICK;
        }
      } else {
        this.rootTick = 0;
      }
    }
    return true;
  }

  dispose() {
    this.body.removeFromParent();
    for (const mesh of this.meshes) {
      mesh.geometry.dispose();
      (mesh.material as THREE.Material).dispose();
    }
  }
}
