import { describe, it, expect } from 'vitest';
import {
  selectModifiers,
  generateEnemy,
  generateSwarm,
  getModifierDisplay,
  getModifierDescription,
} from '../utils/enemy-generator';

const SWARM_CFG = { minEnemies: 3, maxEnemies: 7 };
const SHIELD_AMOUNT = 0.15;

describe('selectModifiers', () => {
  it('should return an array', () => {
    const mods = selectModifiers(20);
    expect(Array.isArray(mods)).toBe(true);
  });

  it('should return at most 2 modifiers', () => {
    for (let i = 0; i < 50; i++) {
      const mods = selectModifiers(50);
      expect(mods.length).toBeLessThanOrEqual(2);
    }
  });

  it('should return empty array for low floors', () => {
    const mods = selectModifiers(1);
    expect(mods.length).toBe(0);
  });

  it('should only return valid modifier types', () => {
    const validMods = ['mage', 'shield', 'armored', 'swarm', 'agile'];
    for (let floor = 1; floor <= 100; floor++) {
      const mods = selectModifiers(floor);
      for (const mod of mods) {
        expect(validMods).toContain(mod);
      }
    }
  });
});

describe('generateEnemy', () => {
  it('should generate enemy with positive HP', () => {
    const enemy = generateEnemy(10);
    expect(enemy.hp).toBeGreaterThan(0);
    expect(enemy.maxHP).toBeGreaterThan(0);
  });

  it('should include modifiers array', () => {
    const enemy = generateEnemy(20);
    expect(Array.isArray(enemy.modifiers)).toBe(true);
  });

  it('should apply armored modifier', () => {
    const enemy = generateEnemy(30, ['armored']);
    expect(enemy.modifiers).toContain('armored');
    expect(enemy.armor).toBeGreaterThan(0);
  });

  it('should apply agile modifier', () => {
    const enemy = generateEnemy(30, ['agile']);
    expect(enemy.modifiers).toContain('agile');
    expect(enemy.dodgeChance).toBeGreaterThan(0);
  });

  it('should apply mage modifier', () => {
    const enemy = generateEnemy(30, ['mage']);
    expect(enemy.modifiers).toContain('mage');
    expect(enemy.barrier).toBeGreaterThan(0);
  });

  it('should apply shield modifier', () => {
    const enemy = generateEnemy(30, ['shield']);
    expect(enemy.modifiers).toContain('shield');
    // Shield modifier now sets shieldPool (flat HP) instead of barrier (percentage)
    expect(enemy.shieldPool).toBeGreaterThanOrEqual(enemy.maxHP * SHIELD_AMOUNT);
  });

  it('should have valid element', () => {
    const enemy = generateEnemy(10);
    expect(enemy.element).toBeTruthy();
    expect(typeof enemy.element).toBe('string');
  });
});

describe('generateSwarm', () => {
  it('should generate multiple enemies', () => {
    const enemies = generateSwarm(20);
    expect(enemies.length).toBeGreaterThanOrEqual(SWARM_CFG.minEnemies);
    expect(enemies.length).toBeLessThanOrEqual(SWARM_CFG.maxEnemies);
  });

  it('each enemy should have reduced HP', () => {
    const enemies = generateSwarm(20);
    for (const enemy of enemies) {
      expect(enemy.hp).toBeGreaterThan(0);
      expect(enemy.maxHP).toBeGreaterThan(0);
    }
  });

  it('should include modifiers', () => {
    const enemies = generateSwarm(20, ['armored']);
    for (const enemy of enemies) {
      expect(enemy.modifiers).toContain('armored');
    }
  });
});

describe('getModifierDisplay', () => {
  it('should return display info for all modifiers', () => {
    const modifiers = ['mage', 'shield', 'armored', 'swarm', 'agile'] as const;
    for (const mod of modifiers) {
      const display = getModifierDisplay(mod);
      expect(display.label).toBeTruthy();
      expect(display.icon).toBeTruthy();
      expect(display.color).toBeTruthy();
      expect(display.desc).toBeTruthy();
    }
  });
});

describe('getModifierDescription', () => {
  it('should return standard for no modifiers', () => {
    expect(getModifierDescription([])).toBe('Standard enemy');
  });

  it('should return modifier labels', () => {
    const desc = getModifierDescription(['armored', 'agile']);
    expect(desc).toContain('Armored');
    expect(desc).toContain('Agile');
  });
});
