/**
 * Magical Weapon — a Magical Object that deals fixed damage.
 *
 * Invariants enforced at construction:
 * - Health is non-negative
 * - Health never exceeds maxHealth
 * - Damage is non-negative
 */
import { Character } from './Character.ts';

export type WeaponStatus = { kind: 'alive' } | { kind: 'destroyed' };

export class MagicalWeapon {
  readonly #health: number;
  readonly #maxHealth: number;
  readonly #status: WeaponStatus;
  readonly #damage: number;
  readonly #owner: Character;

  private constructor(
    health: number,
    maxHealth: number,
    status: WeaponStatus,
    damage: number,
    owner: Character,
  ) {
    this.#health = health;
    this.#maxHealth = maxHealth;
    this.#status = 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 health(): number {
    return this.#health;
  }

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

  get status(): WeaponStatus {
    return this.#status;
  }

  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,
    };
  }
}
