// @vitest-environment jsdom
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { saveAvatar, getAvatar, purgeLegacyHistory } from './storage';

const LEGACY_HISTORY_KEY = 'aisthetix-history';
const AVATAR_KEY = 'aisthetix-avatar';

/**
 * jsdom non lascia intercettare Storage.prototype in modo affidabile, quindi
 * sostituisco l'intero localStorage con un finto che controllo: `pieno` decide
 * quando setItem deve comportarsi come una quota esaurita.
 */
function fintoStorage() {
	const dati = new Map<string, string>();
	const s = {
		pieno: false,
		getItem: ( k: string ) => ( dati.has( k ) ? dati.get( k )! : null ),
		setItem: ( k: string, v: string ) => {
			if ( s.pieno ) {
				const e = new Error( 'quota' );
				e.name = 'QuotaExceededError';
				throw e;
			}
			dati.set( k, v );
		},
		removeItem: ( k: string ) => { dati.delete( k ); },
		clear: () => dati.clear(),
	};
	return s;
}

let finto: ReturnType<typeof fintoStorage>;
const vero = globalThis.localStorage;

beforeEach( () => {
	finto = fintoStorage();
	Object.defineProperty( globalThis, 'localStorage', { value: finto, configurable: true } );
} );
afterEach( () => {
	Object.defineProperty( globalThis, 'localStorage', { value: vero, configurable: true } );
} );

describe( 'purgeLegacyHistory', () => {
	it( 'rimuove la chiave lasciata dalle versioni vecchie del widget', () => {
		finto.setItem( LEGACY_HISTORY_KEY, JSON.stringify( [ { resultImage: 'x' } ] ) );
		expect( purgeLegacyHistory() ).toBe( true );
		expect( finto.getItem( LEGACY_HISTORY_KEY ) ).toBeNull();
	} );

	it( 'non tocca nessun altra chiave e dice che non c era niente da togliere', () => {
		finto.setItem( AVATAR_KEY, 'tienimi' );
		finto.setItem( 'aisthetix-visitor-id', 'anon_1' );
		expect( purgeLegacyHistory() ).toBe( false );
		expect( finto.getItem( AVATAR_KEY ) ).toBe( 'tienimi' );
		expect( finto.getItem( 'aisthetix-visitor-id' ) ).toBe( 'anon_1' );
	} );
} );

describe( 'saveAvatar con la quota esaurita', () => {
	it( 'butta la cronologia vecchia e riesce al secondo tentativo', () => {
		finto.setItem( LEGACY_HISTORY_KEY, 'un-vecchio-blob-enorme' );
		finto.pieno = true;

		// Togliere la cronologia libera spazio: e' esattamente cio che succede
		// in un browser che si porta dietro megabyte di render mai letti.
		const rimuoviReale = finto.removeItem;
		finto.removeItem = ( k: string ) => {
			rimuoviReale( k );
			if ( k === LEGACY_HISTORY_KEY ) { finto.pieno = false; }
		};

		expect( () => saveAvatar( 'data:image/png;base64,AAAA' ) ).not.toThrow();
		expect( finto.getItem( LEGACY_HISTORY_KEY ) ).toBeNull();
		expect( getAvatar()?.imageData ).toBe( 'data:image/png;base64,AAAA' );
	} );

	it( 'segnala comunque il fallimento se non c e niente da recuperare', () => {
		finto.pieno = true;
		expect( () => saveAvatar( 'data:image/png;base64,AAAA' ) ).toThrow( /quota/i );
	} );
} );
