import { StorageMgr, IStorageDriver } from '@common/StorageMgr';

function makeMemoryDriver(): IStorageDriver {
    const m = new Map<string, string>();
    return {
        getItem: (k) => (m.has(k) ? (m.get(k) as string) : null),
        setItem: (k, v) => {
            m.set(k, v);
        },
        removeItem: (k) => {
            m.delete(k);
        },
    };
}

describe('StorageMgr', () => {
    it('returns default when key is missing', () => {
        const sm = new StorageMgr(makeMemoryDriver());
        expect(sm.get('nope', { v: 1 })).toEqual({ v: 1 });
    });

    it('round-trips structured values via JSON', () => {
        const sm = new StorageMgr(makeMemoryDriver());
        const layout = { jump: { x: 100, y: 40 }, shuriken: { x: 820, y: 40 } };
        sm.set('layout', layout);
        expect(sm.get('layout', null)).toEqual(layout);
    });

    it('returns default when value is malformed JSON (req 17.6)', () => {
        const broken: IStorageDriver = {
            getItem: () => '{not json',
            setItem: () => {},
            removeItem: () => {},
        };
        const sm = new StorageMgr(broken);
        expect(sm.get('x', 'fallback')).toBe('fallback');
    });

    it('does not throw when the driver throws (req 17.6)', () => {
        const exploding: IStorageDriver = {
            getItem: () => {
                throw new Error('I/O error');
            },
            setItem: () => {
                throw new Error('I/O error');
            },
            removeItem: () => {},
        };
        const sm = new StorageMgr(exploding);
        expect(() => sm.get('x', 'ok')).not.toThrow();
        expect(sm.get('x', 'ok')).toBe('ok');
        expect(() => sm.set('x', 'value')).not.toThrow();
    });

    it('remove() deletes the key', () => {
        const sm = new StorageMgr(makeMemoryDriver());
        sm.set('k', 123);
        sm.remove('k');
        expect(sm.get('k', -1)).toBe(-1);
    });

    it('setDriver swaps the underlying driver', () => {
        const sm = new StorageMgr(makeMemoryDriver());
        sm.set('k', 1);
        const fresh = makeMemoryDriver();
        sm.setDriver(fresh);
        expect(sm.get('k', 0)).toBe(0);
        sm.set('k', 2);
        expect(sm.get('k', 0)).toBe(2);
    });
});
