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

export class Slime extends Enemy {
  private model: THREE.Group;
  private bodyMesh: THREE.Mesh;
  private time = Math.random() * Math.PI * 2;
  private size: number;

  constructor(size = 0) {
    super();
    this.size = size;

    this.model = new THREE.Group();
    this.fadeOutModel = this.model;
    this.body.add(this.model);

    const color = size === 0 ? 0x33cc88 : 0x66eebb;
    const mat = new THREE.MeshToonMaterial({ color });
    this.bodyMesh = new THREE.Mesh(new THREE.SphereGeometry(0.6, 20, 16), mat);
    this.bodyMesh.position.y = 0.55;
    this.bodyMesh.castShadow = true;
    this.registerFadeMesh(this.bodyMesh);
    this.model.add(this.bodyMesh);

    // Cute eyes (face toward the player: +Z)
    const eyeMat = new THREE.MeshToonMaterial({ color: 0x111122 });
    for (const side of [-1, 1]) {
      const eye = new THREE.Mesh(new THREE.SphereGeometry(0.09, 10, 8), eyeMat);
      eye.position.set(side * 0.18, 0.72, 0.42);
      this.registerFadeMesh(eye);
      this.model.add(eye);
    }

    if (size === 0) {
      this.health = 40;
      this.speed = 3.2;
      this.xp = 12;
      this.contactDps = 25;
    } else {
      this.health = 10;
      this.speed = 4;
      this.xp = 3;
      this.contactDps = 12;
      this.contactRadius = 1.5;
      this.model.scale.setScalar(0.55);
      this.grace = 0.3;
    }
  }

  playAnim() {
    // Procedural visuals only
  }

  updateAnimation(dt: number) {
    if (this.grace > 0) this.grace -= dt;
    this.updateFadeDeath(dt, { duration: 0.7, shrink: 0.9 });
  }

  update(dt: number, game: Game) {
    this.time += dt;

    // Squishy pulse
    const pulse = 1 + Math.sin(this.time * 5) * 0.08;
    this.model.scale.y = (this.size === 0 ? 1 : 0.55) * pulse;
    const squash = 1 + (1 - pulse) * 0.5;
    this.model.scale.x = (this.size === 0 ? 1 : 0.55) * squash;
    this.model.scale.z = this.model.scale.x;

    // Hop-wiggle toward the player
    const toPlayer = new THREE.Vector3()
      .subVectors(game.player.body.position, this.body.position);
    toPlayer.y = 0;
    const dist = toPlayer.length();
    if (dist > 0.1) {
      const dir = toPlayer.normalize();
      this.body.lookAt(
        this.body.position.x + dir.x,
        this.body.position.y,
        this.body.position.z + dir.z
      );
      let moveDir = dir.multiplyScalar(this.speed);
      if (this.knockback > 0) {
        moveDir = dir.multiplyScalar(-this.speed);
        this.knockback -= dt;
      }
      this.body.position.x += moveDir.x * dt;
      this.body.position.z += moveDir.z * dt;
      game.clampToArena(this.body.position);
    }
  }

  protected onDeath(game: Game) {
    this.beginFadeDeath();
    if (this.size === 0) {
      playSound('spawn', 0.5);
      for (let i = 0; i < 2; i++) {
        const child = new Slime(1);
        game.spawnEnemyInstance(
          child,
          this.body.position.x + (Math.random() - 0.5) * 1.2,
          this.body.position.z + (Math.random() - 0.5) * 1.2,
          0.1
        );
      }
    }
  }
}
