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

export class Bat extends Enemy {
  private model: THREE.Group;
  private wingL: THREE.Mesh;
  private wingR: THREE.Mesh;
  private flapTime = Math.random() * Math.PI * 2;
  private flyTime = Math.random() * Math.PI * 2;

  constructor() {
    super();
    this.health = 25;
    this.speed = 8;
    this.xp = 10;

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

    const furMat = new THREE.MeshToonMaterial({ color: 0x5a4568 });

    // Body
    const bodyMesh = new THREE.Mesh(new THREE.SphereGeometry(0.3, 14, 12), furMat);
    bodyMesh.scale.set(1, 0.9, 1.3);
    bodyMesh.castShadow = true;
    this.registerFadeMesh(bodyMesh);
    this.model.add(bodyMesh);

    // Head with ears (face toward the player: +Z)
    const head = new THREE.Mesh(new THREE.SphereGeometry(0.18, 12, 10), furMat);
    head.position.set(0, 0.15, 0.3);
    this.registerFadeMesh(head);
    this.model.add(head);

    for (const side of [-1, 1]) {
      const ear = new THREE.Mesh(new THREE.ConeGeometry(0.07, 0.18, 6), furMat);
      ear.position.set(side * 0.12, 0.32, 0.25);
      this.registerFadeMesh(ear);
      this.model.add(ear);
    }

    // Eyes
    const eyeMat = new THREE.MeshToonMaterial({ color: 0xff2222 });
    for (const side of [-1, 1]) {
      const eye = new THREE.Mesh(new THREE.SphereGeometry(0.035, 8, 8), eyeMat);
      eye.position.set(side * 0.07, 0.16, 0.42);
      this.registerFadeMesh(eye);
      this.model.add(eye);
    }

    // Wings (hinged at the body, flap via rotation.z)
    const wingGeom = new THREE.PlaneGeometry(0.75, 0.5, 1, 4);
    wingGeom.translate(0.3, 0, 0);
    const wingMat = new THREE.MeshToonMaterial({
      color: 0x443355,
      side: THREE.DoubleSide,
      transparent: true,
      opacity: 0.9,
    });
    this.wingL = new THREE.Mesh(wingGeom, wingMat);
    this.wingR = new THREE.Mesh(wingGeom.clone(), wingMat);
    this.wingL.position.set(-0.3, 0.05, 0);
    this.wingR.position.set(0.3, 0.05, 0);
    this.registerFadeMesh(this.wingL);
    this.registerFadeMesh(this.wingR);
    this.model.add(this.wingL, this.wingR);
  }

  playAnim() {
    // Procedural visuals only
  }

  updateAnimation(dt: number) {
    this.updateFadeDeath(dt, { duration: 0.7, sink: 3 });
  }

  update(dt: number, game: Game) {
    this.flapTime += dt * 14;
    this.flyTime += dt * 3;

    const flap = Math.sin(this.flapTime) * 0.9;
    this.wingL.rotation.z = -1.1 - flap;
    this.wingR.rotation.z = 1.1 + flap;

    // Bob up and down while swooping at the player
    this.body.position.y = 1.0 + Math.sin(this.flyTime) * 0.5;

    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
      );
      // Slight zigzag
      const perp = new THREE.Vector3(-dir.z, 0, dir.x)
        .multiplyScalar(Math.sin(this.flyTime * 2.2) * 0.6);

      let moveDir = dir.clone().multiplyScalar(this.speed).add(perp);
      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();
  }
}
