
import { describe, it, expect } from "vitest";
import { getClosestVisibleEnemy } from "../gameplay/CombatLogic";
import type { World, CombatantActor } from "../../core/types";

describe("CombatLogic - getClosestVisibleEnemy", () => {
    
    // Helper to create valid default stats for testing
    const createMockStats = () => ({
        hp: 10, maxHp: 10, attack: 1, defense: 0,
        accuracy: 100, evasion: 0, critChance: 0, critMultiplier: 0,
        blockChance: 0, lifesteal: 0, mana: 0, maxMana: 0,
        level: 1, exp: 0, expToNextLevel: 100, luck: 0,
        statPoints: 0, skillPoints: 0,
        strength: 10, dexterity: 10, intelligence: 10,
        passiveNodes: []
    });

    it("should return null if no enemies are visible", () => {
        const world: World = {
            width: 10,
            height: 10,
            tiles: new Array(100).fill(0),
            actors: new Map(),
            exit: { x: 9, y: 9 }
        };

        const player: CombatantActor = {
            id: 0, category: "combatant", type: "player", pos: { x: 5, y: 5 }, isPlayer: true,
            stats: createMockStats(),
            inventory: { gold: 0, items: [] }, equipment: {},
            speed: 1, energy: 0
        };
        world.actors.set(0, player);

        const enemy: CombatantActor = {
            id: 1, category: "combatant", type: "rat", pos: { x: 6, y: 6 }, isPlayer: false,
            stats: createMockStats(),
            speed: 1, energy: 0
        };
        world.actors.set(1, enemy);

        // Mock seenArray where nothing is seen
        const seenArray = new Uint8Array(100).fill(0);

        const result = getClosestVisibleEnemy(world, player.pos, seenArray, 10);
        expect(result).toBeNull();
    });

    it("should return the closest visible enemy", () => {
        const world: World = {
            width: 10,
            height: 10,
            tiles: new Array(100).fill(0),
            actors: new Map(),
            exit: { x: 9, y: 9 }
        };

        const player: CombatantActor = {
            id: 0, category: "combatant", type: "player", pos: { x: 5, y: 5 }, isPlayer: true,
            stats: createMockStats(),
            inventory: { gold: 0, items: [] }, equipment: {},
            speed: 1, energy: 0
        };
        world.actors.set(0, player);

        // Enemy 1: Close (distance sqrt(2) ~= 1.41)
        const enemy1: CombatantActor = {
            id: 1, category: "combatant", type: "rat", pos: { x: 6, y: 6 }, isPlayer: false,
            stats: createMockStats(),
            speed: 1, energy: 0
        };
        world.actors.set(1, enemy1);

        // Enemy 2: Farther (distance sqrt(8) ~= 2.82)
        const enemy2: CombatantActor = {
            id: 2, category: "combatant", type: "rat", pos: { x: 7, y: 7 }, isPlayer: false,
            stats: createMockStats(),
            speed: 1, energy: 0
        };
        world.actors.set(2, enemy2);

        // Mock seenArray where both are seen
        const seenArray = new Uint8Array(100).fill(0);
        seenArray[6 * 10 + 6] = 1; // Enemy 1 visible
        seenArray[7 * 10 + 7] = 1; // Enemy 2 visible

        const result = getClosestVisibleEnemy(world, player.pos, seenArray, 10);
        expect(result).toEqual({ x: 6, y: 6 });
    });

    it("should ignore invisible closer enemies and select visible farther ones", () => {
        const world: World = {
            width: 10,
            height: 10,
            tiles: new Array(100).fill(0),
            actors: new Map(),
            exit: { x: 9, y: 9 }
        };

        const player: CombatantActor = {
            id: 0, category: "combatant", type: "player", pos: { x: 5, y: 5 }, isPlayer: true,
            stats: createMockStats(),
            inventory: { gold: 0, items: [] }, equipment: {},
            speed: 1, energy: 0
        };
        world.actors.set(0, player);

        // Enemy 1: Close but invisible
        const enemy1: CombatantActor = {
            id: 1, category: "combatant", type: "rat", pos: { x: 6, y: 6 }, isPlayer: false,
            stats: createMockStats(),
            speed: 1, energy: 0
        };
        world.actors.set(1, enemy1);

        // Enemy 2: Farther but visible
        const enemy2: CombatantActor = {
            id: 2, category: "combatant", type: "rat", pos: { x: 8, y: 5 }, isPlayer: false,
            stats: createMockStats(),
            speed: 1, energy: 0
        };
        world.actors.set(2, enemy2);

        // Mock seenArray where only Enemy 2 is seen
        const seenArray = new Uint8Array(100).fill(0);
        seenArray[5 * 10 + 8] = 1; // Enemy 2 visible at (8,5)

        const result = getClosestVisibleEnemy(world, player.pos, seenArray, 10);
        expect(result).toEqual({ x: 8, y: 5 });
    });
});
