import { describe, it, expect, beforeEach } from 'vitest';
import { applyEnemyDefenses } from '../stores/pipelines/combat-tick';
import type { EnemyState } from '../types';

// ─── Helpers ──────────────────────────────────────────────────────────────────

function makeEnemy(overrides: Partial<EnemyState> = {}): EnemyState {
  return {
    id: 'test_enemy',
    name: 'Test Enemy',
    hp: 100,
    maxHP: 100,
    armor: 0,
    dodgeChance: 0,
    barrier: 0,
    element: 'fire',
    activeEffects: [],
    effectiveArmor: 0,
    ...overrides,
  };
}

// ═══════════════════════════════════════════════════════════════════════════════
// CURSE AMPLIFICATION TESTS (spec §6.3, issue #286)
// ═══════════════════════════════════════════════════════════════════════════════

describe('Curse amplification (spec §6.3)', () => {
  beforeEach(() => {
    // Reset any global state if needed
  });

  it('should not amplify damage when enemy has no curse effect', () => {
    const enemy = makeEnemy();
    const logs: string[] = [];
    const result = applyEnemyDefenses(100, enemy, 'combat', (msg) => logs.push(msg));
    expect(result).toBe(100);
  });

  it('should amplify damage by curse magnitude (single curse)', () => {
    const enemy = makeEnemy({
      activeEffects: [
        { type: 'curse', remainingDuration: 3, magnitude: 0.20, source: 'spell' },
      ],
    });
    const logs: string[] = [];
    const result = applyEnemyDefenses(100, enemy, 'combat', (msg) => logs.push(msg));
    // 100 * (1 + 0.20) = 120
    expect(result).toBe(120);
  });

  it('should stack multiple curse effects multiplicatively', () => {
    const enemy = makeEnemy({
      activeEffects: [
        { type: 'curse', remainingDuration: 3, magnitude: 0.20, source: 'spell' },
        { type: 'curse', remainingDuration: 2, magnitude: 0.15, source: 'spell' },
      ],
    });
    const logs: string[] = [];
    const result = applyEnemyDefenses(100, enemy, 'combat', (msg) => logs.push(msg));
    // 100 * (1 + 0.20) * (1 + 0.15) = 100 * 1.20 * 1.15 = 138
    expect(result).toBe(138);
  });

  it('should apply curse amplification before armor reduction', () => {
    const enemy = makeEnemy({
      armor: 0.5,
      effectiveArmor: 0.5,
      activeEffects: [
        { type: 'curse', remainingDuration: 3, magnitude: 0.20, source: 'spell' },
      ],
    });
    const logs: string[] = [];
    const result = applyEnemyDefenses(100, enemy, 'combat', (msg) => logs.push(msg));
    // Curse first: 100 * 1.20 = 120
    // Then armor: 120 * (1 - 0.5) = 60
    expect(result).toBe(60);
  });

  it('should apply curse amplification before barrier absorption', () => {
    const enemy = makeEnemy({
      barrier: 0.5,
      activeEffects: [
        { type: 'curse', remainingDuration: 3, magnitude: 0.20, source: 'spell' },
      ],
    });
    const logs: string[] = [];
    const result = applyEnemyDefenses(100, enemy, 'combat', (msg) => logs.push(msg));
    // Curse first: 100 * 1.20 = 120
    // Then barrier: 120 * (1 - 0.5) = 60
    expect(result).toBe(60);
  });

  it('should apply curse amplification before dodge check', () => {
    // Curse amplifies damage before dodge, but dodge still works
    const enemy = makeEnemy({
      dodgeChance: 0, // No dodge for deterministic test
      activeEffects: [
        { type: 'curse', remainingDuration: 3, magnitude: 0.30, source: 'spell' },
      ],
    });
    const logs: string[] = [];
    const result = applyEnemyDefenses(100, enemy, 'combat', (msg) => logs.push(msg));
    // Curse: 100 * 1.30 = 130, no dodge
    expect(result).toBe(130);
  });

  it('should ignore non-curse effects when calculating amplification', () => {
    const enemy = makeEnemy({
      activeEffects: [
        { type: 'burn', remainingDuration: 3, magnitude: 5, source: 'spell' },
        { type: 'curse', remainingDuration: 3, magnitude: 0.25, source: 'spell' },
        { type: 'freeze', remainingDuration: 2, magnitude: 0, source: 'spell' },
        { type: 'armor_corrode', remainingDuration: 4, magnitude: 0.15, source: 'spell' },
      ],
    });
    const logs: string[] = [];
    const result = applyEnemyDefenses(100, enemy, 'combat', (msg) => logs.push(msg));
    // Only curse applies: 100 * 1.25 = 125
    expect(result).toBe(125);
  });

  it('should return damage unchanged for null enemy even with curse', () => {
    const logs: string[] = [];
    const result = applyEnemyDefenses(100, null, 'combat', (msg) => logs.push(msg));
    expect(result).toBe(100);
  });

  it('should handle enemy with zero-magnitude curse (no amplification)', () => {
    const enemy = makeEnemy({
      activeEffects: [
        { type: 'curse', remainingDuration: 3, magnitude: 0, source: 'spell' },
      ],
    });
    const logs: string[] = [];
    const result = applyEnemyDefenses(100, enemy, 'combat', (msg) => logs.push(msg));
    // 100 * (1 + 0) = 100
    expect(result).toBe(100);
  });
});
