import { describe, expect, it } from 'vitest';
import {
    dialogueLayer,
    enemiesLayer,
    gameLayer,
    heroLayer,
    npcsLayer,
    type EnemySnapshot,
    type NpcSnapshot
} from '../snapshot';

describe('снапшот агента — слои', () => {
    it('герой: позиция округляется до 3 знаков, остальное копируется', () => {
        const layer = heroLayer({
            tile: { x: 12, y: 8 },
            pos: { x: 1.23456, y: 5.0001 },
            hp: 9,
            maxHp: 12,
            facing: 'side',
            moving: false,
            invuln: false,
            inHazard: null
        });
        expect(layer.hero).toMatchObject({
            tile: { x: 12, y: 8 },
            pos: { x: 1.235, y: 5 },
            hp: 9,
            maxHp: 12,
            facing: 'side'
        });
    });

    it('враги: поля на месте, позиция округлена', () => {
        const e: EnemySnapshot = {
            kind: 'ash',
            state: 'chase',
            hp: 4,
            pos: { x: 0.123456, y: 2.5 },
            asleep: true,
            dead: false
        };
        const layer = enemiesLayer([e]);
        expect(layer.enemies).toEqual([
            { kind: 'ash', state: 'chase', hp: 4, pos: { x: 0.123, y: 2.5 }, asleep: true, dead: false }
        ]);
    });

    it('NPC: копия с met, без ссылок на источник', () => {
        const n: NpcSnapshot = { id: 'elder', name: 'Ирвин', tile: { x: 20, y: 12 }, met: false };
        const layer = npcsLayer([n]);
        const out = (layer.npcs as unknown as NpcSnapshot[])[0]!;
        expect(out).toEqual(n);
        expect(out).not.toBe(n);
    });

    it('диалог: объект проходит, null остаётся null', () => {
        const d = { id: 'elder', nodeId: 'n1', speaker: 'Ирвин', text: 'Привет', choices: [], waitingForChoice: false };
        expect(dialogueLayer(d).dialogue).toEqual(d);
        expect(dialogueLayer(null).dialogue).toBeNull();
    });

    it('слой игры: флаги/вары/сумка копируются защитно', () => {
        const flags = ['metElder'];
        const vars = { flowers: 2 };
        const inv = [{ id: 'flower', count: 2 }];
        const layer = gameLayer({ flags, vars, inventory: inv });
        expect(layer).toEqual({ flags: ['metElder'], vars: { flowers: 2 }, inventory: [{ id: 'flower', count: 2 }] });
        // Мутация источника не меняет слой.
        flags.push('x');
        vars.flowers = 99;
        inv[0]!.count = 99;
        expect(layer.flags).toEqual(['metElder']);
        expect(layer.vars).toEqual({ flowers: 2 });
        expect(layer.inventory[0]!.count).toBe(2);
    });
});