/**
 * Magical Weapon — a Magical Object that deals fixed damage.
 *
 * Inherits health/status management from MagicalObject.
 * Invariants enforced at construction:
 * - Damage is non-negative
 */
import { Character } from '../characters/Character.ts';
import { MagicalObject } from './MagicalObject.ts';
import type { DamageDealer } from './magical-object-types.ts';

export class MagicalWeapon extends MagicalObject implements DamageDealer {
  readonly #damage: number;
  readonly #owner: Character;

  private constructor(
    health: number,
    maxHealth: number,
    status: { readonly kind: 'alive' } | { readonly kind: 'destroyed' },
    damage: number,
    owner: Character,
  ) {
    super(health, maxHealth, status);
    this.#damage = damage;
    this.#owner = owner;
  }

  static create({
    maxHealth,
    damage,
    owner,
  }: {
    maxHealth: number;
    damage: number;
    owner: Character;
  }): MagicalWeapon {
    if (maxHealth < 0) throw new Error('MaxHealth cannot be negative');
    if (damage < 0) throw new Error('Damage cannot be negative');
    return new MagicalWeapon(maxHealth, maxHealth, { kind: 'alive' }, damage, owner);
  }

  get damage(): number {
    return this.#damage;
  }

  get owner(): Character {
    return this.#owner;
  }

  /** Use this weapon to deal damage. Returns updated weapon and target. */
  use(target: Character): { weapon: MagicalWeapon; target: Character } {
    // Destroyed weapons can't be used
    if (this.status.kind === 'destroyed') {
      return { weapon: this, target };
    }
    // Deal fixed damage
    const newTargetHealth = Math.max(0, target.health.value - this.#damage);
    const newTargetStatus = newTargetHealth === 0 ? { kind: 'dead' as const } : target.status;
    const newTarget = Character.createWithHealthAndStatus({
      name: target.name,
      level: target.level,
      health: newTargetHealth,
      status: newTargetStatus,
    });
    // Reduce weapon health by 1
    const newWeaponHealth = this.health - 1;
    const newWeaponStatus =
      newWeaponHealth === 0 ? { kind: 'destroyed' as const } : { kind: 'alive' as const };
    return {
      weapon: new MagicalWeapon(
        newWeaponHealth,
        this.maxHealth,
        newWeaponStatus,
        this.#damage,
        this.#owner,
      ),
      target: newTarget,
    };
  }
}
