import { describe, it, expect } from 'vitest';
import { applyAction } from '../simulation/simulation';
import { type World, type Actor, type EntityId } from '../../core/types';

describe('Combat Simulation', () => {
  const createTestWorld = (actors: Map<EntityId, Actor>): World => ({
    width: 10,
    height: 10,
    tiles: new Array(100).fill(0),
    actors,
    exit: { x: 9, y: 9 }
  });

  describe('applyAction - attack', () => {
    it('should deal damage when player attacks enemy', () => {
      const actors = new Map<EntityId, Actor>();
      actors.set(1, {
        id: 1,
        isPlayer: true,
        pos: { x: 3, y: 3 },
        speed: 100,
        energy: 0,
        stats: { maxHp: 20, hp: 20, attack: 5, defense: 2 }
      });
      actors.set(2, {
        id: 2,
        isPlayer: false,
        pos: { x: 4, y: 3 },
        speed: 100,
        energy: 0,
        stats: { maxHp: 10, hp: 10, attack: 3, defense: 1 }
      });

      const world = createTestWorld(actors);
      const events = applyAction(world, 1, { type: 'attack', targetId: 2 });

      const enemy = world.actors.get(2)!;
      expect(enemy.stats!.hp).toBeLessThan(10);
      
      // Should have attack event
      expect(events.some(e => e.type === 'attacked')).toBe(true);
    });

    it('should kill enemy when damage exceeds hp', () => {
      const actors = new Map<EntityId, Actor>();
      actors.set(1, {
        id: 1,
        isPlayer: true,
        pos: { x: 3, y: 3 },
        speed: 100,
        energy: 0,
        stats: { maxHp: 20, hp: 20, attack: 50, defense: 2 }
      });
      actors.set(2, {
        id: 2,
        isPlayer: false,
        pos: { x: 4, y: 3 },
        speed: 100,
        energy: 0,
        stats: { maxHp: 10, hp: 10, attack: 3, defense: 1 }
      });

      const world = createTestWorld(actors);
      const events = applyAction(world, 1, { type: 'attack', targetId: 2 });

      // Enemy should be removed from world
      expect(world.actors.has(2)).toBe(false);
      
      // Should have killed event
      expect(events.some(e => e.type === 'killed')).toBe(true);
    });

    it('should apply defense to reduce damage', () => {
      const actors = new Map<EntityId, Actor>();
      actors.set(1, {
        id: 1,
        isPlayer: true,
        pos: { x: 3, y: 3 },
        speed: 100,
        energy: 0,
        stats: { maxHp: 20, hp: 20, attack: 5, defense: 2 }
      });
      actors.set(2, {
        id: 2,
        isPlayer: false,
        pos: { x: 4, y: 3 },
        speed: 100,
        energy: 0,
        stats: { maxHp: 10, hp: 10, attack: 3, defense: 3 }
      });

      const world = createTestWorld(actors);
      applyAction(world, 1, { type: 'attack', targetId: 2 });

      const enemy = world.actors.get(2)!;
      const damage = 10 - enemy.stats!. hp;
      
      // Damage should be reduced by defense (5 attack - 3 defense = 2 damage)
      expect(damage).toBe(2);
    });
  });

  describe('applyAction - move', () => {
    it('should move actor to new position', () => {
      const actors = new Map<EntityId, Actor>();
      actors.set(1, {
        id: 1,
        isPlayer: true,
        pos: { x: 3, y: 3 },
        speed: 100,
        energy: 0,
        stats: { maxHp: 20, hp: 20, attack: 5, defense: 2 }
      });

      const world = createTestWorld(actors);
      const events = applyAction(world, 1, { type: 'move', dx: 1, dy: 0 });

      const player = world.actors.get(1)!;
      expect(player.pos).toEqual({ x: 4, y: 3 });
      
      // Should have moved event
      expect(events.some(e => e.type === 'moved')).toBe(true);
    });
  });
});
