import { describe, it, expect } from 'vitest';
import { SaveManager, type StorageLike } from '../SaveManager';

function memoryStorage(): StorageLike {
    const map = new Map<string, string>();
    return {
        getItem: (k) => map.get(k) ?? null,
        setItem: (k, v) => void map.set(k, v),
        removeItem: (k) => void map.delete(k),
        key: (i) => [...map.keys()][i] ?? null,
        get length() {
            return map.size;
        }
    };
}

describe('SaveManager', () => {
    it('сохраняет и загружает по слотам', () => {
        const sm = new SaveManager(memoryStorage());
        sm.save('slot1', { x: 3, y: 4 });
        expect(sm.load<{ x: number; y: number }>('slot1')).toEqual({ x: 3, y: 4 });
        expect(sm.load('unknown')).toBeNull();
    });

    it('битый JSON -> null', () => {
        const storage = memoryStorage();
        storage.setItem('save:broken', '{oops');
        const sm = new SaveManager(storage);
        expect(sm.load('broken')).toBeNull();
    });

    it('listSlots и delete', () => {
        const sm = new SaveManager(memoryStorage());
        sm.save('a', 1);
        sm.save('b', 2);
        expect(sm.listSlots().sort()).toEqual(['a', 'b']);
        sm.delete('a');
        expect(sm.listSlots()).toEqual(['b']);
    });

    it('мета пишется в параллельный ключ и читается без сейва', () => {
        const storage = memoryStorage();
        const sm = new SaveManager(storage);
        sm.save('slot1', { hp: 3 }, { title: 'Луга', savedAt: 42, version: 3 });
        expect(storage.getItem('save:slot1')).not.toContain('Луга');
        expect(sm.slotMeta('slot1')).toEqual({ title: 'Луга', savedAt: 42, version: 3 });
        expect(sm.list()).toEqual([{ slot: 'slot1', meta: { title: 'Луга', savedAt: 42, version: 3 } }]);
    });

    it('сейв без меты и битая мета -> slotMeta null, сейв читается', () => {
        const storage = memoryStorage();
        const sm = new SaveManager(storage);
        sm.save('old', { hp: 1 }); // без меты — как старые сейвы
        expect(sm.slotMeta('old')).toBeNull();
        storage.setItem('save:meta:broken', '{oops');
        expect(sm.slotMeta('broken')).toBeNull();
    });

    it('delete чистит и сейв, и мету; listSlots без meta:*', () => {
        const sm = new SaveManager(memoryStorage());
        sm.save('a', 1, { title: 'A' });
        expect(sm.listSlots()).toEqual(['a']); // meta-ключ не в списке
        sm.delete('a');
        expect(sm.has('a')).toBe(false);
        expect(sm.slotMeta('a')).toBeNull();
    });
});