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

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

describe('Settings', () => {
    it('отсутствующий слот даёт настройки по умолчанию', () => {
        const s = new Settings(memoryStorage());
        s.load();
        expect(s.data.master).toBe(1);
        expect(s.data.lang).toBe('ru');
    });

    it('update применяет патч, сохраняет в хранилище и уведомляет слушателей', () => {
        const storage = memoryStorage();
        const s = new Settings(storage);
        s.load();

        let notified = 0;
        s.onChange(() => notified++);
        s.update({ master: 0.5, music: 0.2 });

        expect(notified).toBe(1);
        expect(s.data.master).toBe(0.5);
        const saved = JSON.parse(storage.store.get('settings')!);
        expect(saved.master).toBe(0.5);
        expect(saved.music).toBe(0.2);

        // новый экземпляр читает то же
        const s2 = new Settings(storage);
        s2.load();
        expect(s2.data.master).toBe(0.5);
    });

    it('битый JSON в хранилище не роняет загрузку', () => {
        const storage = memoryStorage();
        storage.store.set('settings', '{oops');
        const s = new Settings(storage);
        expect(() => s.load()).not.toThrow();
        expect(s.data.master).toBe(1);
    });

    it('extra хранит произвольные значения', () => {
        const s = new Settings(memoryStorage());
        s.load();
        s.update({ extra: { hintSeen: true } });
        expect(s.getExtra('hintSeen')).toBe(true);
    });
});