// ─── Golem Combat Helpers Unit Tests (Issue #313) ──────────────────────────────
// Unit tests for computeBasicAttackDamage and resolveEnchantmentEffects.

import { describe, it, expect } from 'vitest';
import { computeBasicAttackDamage, resolveEnchantmentEffects } from './golem-combat-helpers';

// ─── computeBasicAttackDamage ────────────────────────────────────────────────

describe('computeBasicAttackDamage', () => {
  it('returns baseDamage with no armor and no elemental effect', () => {
    const dmg = computeBasicAttackDamage(
      { baseDamage: 10, armorPierce: 0, element: undefined },
      0, 0, 'fire',
    );
    expect(dmg).toBe(10);
  });

  it('applies elemental bonus for super effective matchup', () => {
    // Water vs Fire = 1.5x (water is opposite of fire)
    const dmg = computeBasicAttackDamage(
      { baseDamage: 10, armorPierce: 0, element: 'water' },
      0, 0, 'fire',
    );
    expect(dmg).toBe(15);
  });

  it('applies elemental penalty for weak matchup', () => {
    // Lightning vs Earth = 0.75x (lightning is weak to earth)
    const dmg = computeBasicAttackDamage(
      { baseDamage: 10, armorPierce: 0, element: 'lightning' },
      0, 0, 'earth',
    );
    expect(dmg).toBe(7.5);
  });

  it('applies same-element bonus', () => {
    const dmg = computeBasicAttackDamage(
      { baseDamage: 10, armorPierce: 0, element: 'fire' },
      0, 0, 'fire',
    );
    expect(dmg).toBe(12.5);
  });

  it('never returns negative damage', () => {
    const dmg = computeBasicAttackDamage(
      { baseDamage: 10, armorPierce: 0, element: undefined },
      0, 0.99, 'fire',
    );
    expect(dmg).toBeGreaterThanOrEqual(0);
  });

  it('combines elemental bonus and armor pierce', () => {
    // Water vs Fire = 1.5x, then armor pierce adds to damage multiplier
    // dmg = 10 * 1.5 * (1 + 0.25) = 18.75
    const dmg = computeBasicAttackDamage(
      { baseDamage: 10, armorPierce: 0.25, element: 'water' },
      0, 0.5, 'fire',
    );
    expect(dmg).toBeCloseTo(18.75, 5);
  });

  it('doubles damage when armorPierce is 1.0', () => {
    // dmg = 10 * (1 + 1.0) = 20
    const dmg = computeBasicAttackDamage(
      { baseDamage: 10, armorPierce: 1.0, element: undefined },
      0, 0.8, 'fire',
    );
    expect(dmg).toBe(20);
  });

  it('returns base damage when armorPierce is 0', () => {
    // dmg = 10 * (1 + 0) = 10
    const dmg = computeBasicAttackDamage(
      { baseDamage: 10, armorPierce: 0, element: undefined },
      0, 0.5, 'fire',
    );
    expect(dmg).toBe(10);
  });

  it('stacks enchantment armorPierce with frame armorPierce', () => {
    // totalPierce = 0.5 + 0.15 = 0.65
    // dmg = 20 * (1 + 0.65) = 33
    const totalPierce = 0.5 + 0.15;
    const dmg = computeBasicAttackDamage(
      { baseDamage: 20, armorPierce: 0.5, element: undefined },
      0.15, 0.4, 'fire',
    );
    expect(dmg).toBe(20 * (1 + totalPierce));
  });
});

// ─── resolveEnchantmentEffects ────────────────────────────────────────────────

describe('resolveEnchantmentEffects', () => {
  it('resolves sword_fire to burn effect', () => {
    const effects = resolveEnchantmentEffects(['sword_fire']);
    expect(effects).toHaveLength(1);
    expect(effects[0].type).toBe('burn');
    expect(effects[0].magnitude).toBe(3);
  });

  it('resolves sword_frost to slow effect', () => {
    const effects = resolveEnchantmentEffects(['sword_frost']);
    expect(effects).toHaveLength(1);
    expect(effects[0].type).toBe('slow');
  });

  it('resolves sword_metal to armorPierce effect', () => {
    const effects = resolveEnchantmentEffects(['sword_metal']);
    expect(effects).toHaveLength(1);
    expect(effects[0].type).toBe('armorPierce');
    expect(effects[0].magnitude).toBe(0.15);
  });

  it('resolves sword_lightning to shock effect', () => {
    const effects = resolveEnchantmentEffects(['sword_lightning']);
    expect(effects).toHaveLength(1);
    expect(effects[0].type).toBe('shock');
  });

  it('resolves sword_shadow to weaken effect', () => {
    const effects = resolveEnchantmentEffects(['sword_shadow']);
    expect(effects).toHaveLength(1);
    expect(effects[0].type).toBe('weaken');
  });

  it('returns empty array for unknown enchantment IDs', () => {
    const effects = resolveEnchantmentEffects(['nonexistent_enchant']);
    expect(effects).toHaveLength(0);
  });

  it('resolves multiple enchantments', () => {
    const effects = resolveEnchantmentEffects(['sword_fire', 'sword_lightning', 'sword_shadow']);
    expect(effects).toHaveLength(3);
    const types = effects.map(e => e.type);
    expect(types).toContain('burn');
    expect(types).toContain('shock');
    expect(types).toContain('weaken');
  });

  it('handles empty array', () => {
    const effects = resolveEnchantmentEffects([]);
    expect(effects).toHaveLength(0);
  });
});
