import { Injectable } from '@angular/core'; import { GeneratedMedia } from '../models/openrouter.models'; @Injectable({ providedIn: 'root' }) export class StorageService { private readonly ACTIVE_PROVIDER = 'ai_active_provider'; private readonly API_KEY_OPENROUTER = 'openrouter_api_key'; private readonly API_KEY_REPLICATE = 'replicate_api_key'; private readonly SELECTED_MODEL = 'openrouter_selected_model'; private readonly MEDIA_HISTORY = 'openrouter_media_history'; private readonly DEFAULT_ENV_API_KEY = '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'; // Cache in-memory per preservare i dataURL dei video ed audio per la sessione corrente private urlCache = new Map(); getActiveProvider(): 'openrouter' | 'replicate' { const p = localStorage.getItem(this.ACTIVE_PROVIDER); return (p === 'replicate') ? 'replicate' : 'openrouter'; } setActiveProvider(provider: 'openrouter' | 'replicate'): void { localStorage.setItem(this.ACTIVE_PROVIDER, provider); } getApiKey(provider?: 'openrouter' | 'replicate'): string { const p = provider || this.getActiveProvider(); if (p === 'replicate') { return localStorage.getItem(this.API_KEY_REPLICATE) || ''; } return localStorage.getItem(this.API_KEY_OPENROUTER) || this.DEFAULT_ENV_API_KEY; } setApiKey(key: string, provider?: 'openrouter' | 'replicate'): void { const p = provider || this.getActiveProvider(); if (p === 'replicate') { localStorage.setItem(this.API_KEY_REPLICATE, key.trim()); } else { localStorage.setItem(this.API_KEY_OPENROUTER, key.trim()); } } private readonly REPLICATE_BUDGET = 'replicate_initial_budget'; private readonly REPLICATE_USAGE = 'replicate_total_usage'; getReplicateBudget(): number { const val = localStorage.getItem(this.REPLICATE_BUDGET); return val !== null ? parseFloat(val) : 11.72; // Credito rimanente Replicate } setReplicateBudget(budget: number): void { localStorage.setItem(this.REPLICATE_BUDGET, Math.max(0, budget).toString()); } getReplicateUsage(): number { const val = localStorage.getItem(this.REPLICATE_USAGE); return val ? parseFloat(val) || 0 : 0.07; } getReplicateRemainingCredits(): number { const currentRemaining = localStorage.getItem('replicate_remaining_credits'); if (currentRemaining !== null) { return Math.max(0, parseFloat(currentRemaining) || 0); } const budget = this.getReplicateBudget(); return Math.max(0, budget); } setReplicateRemainingCredits(credits: number): void { localStorage.setItem('replicate_remaining_credits', Math.max(0, credits).toString()); } addReplicateUsage(amount: number): number { const currentUsage = this.getReplicateUsage(); const updatedUsage = Math.max(0, currentUsage + amount); localStorage.setItem(this.REPLICATE_USAGE, updatedUsage.toString()); // Scala direttamente dai crediti rimanenti Replicate const currentRemaining = this.getReplicateRemainingCredits(); const updatedRemaining = Math.max(0, currentRemaining - amount); this.setReplicateRemainingCredits(updatedRemaining); return updatedUsage; } getSelectedModel(): string { return localStorage.getItem(this.SELECTED_MODEL) || 'recraft-ai/recraft-v3'; } setSelectedModel(model: string): void { localStorage.setItem(this.SELECTED_MODEL, model); } getHistory(): GeneratedMedia[] { try { const data = localStorage.getItem(this.MEDIA_HISTORY); const rawList: GeneratedMedia[] = data ? JSON.parse(data) : []; return rawList.map(item => { let costDisplay = item.costDisplay; // Fix per eventuali elementi salvati precedentemente con il tempo in secondi invece del costo in dollari if (costDisplay) { const numMatch = costDisplay.match(/[\d.]+/); if (numMatch && parseFloat(numMatch[0]) > 20) { // Era il tempo di predict in secondi (es. 129s) invece del costo reale const durationEst = 5; costDisplay = `$${(0.067 * durationEst).toFixed(4)}`; } } return { ...item, costDisplay: costDisplay || '$0.3350', url: item.url || this.urlCache.get(item.id) || '' }; }); } catch (e) { console.warn('Impossibile leggere lo storico da localStorage', e); return []; } } saveMediaItem(item: GeneratedMedia): void { if (item.id && item.url) { this.urlCache.set(item.id, item.url); } let history = this.getHistory(); // Per evitare di superare i 5MB di quota di localStorage, rimuovi la stringa base64 se supera i 50KB nello storage su disco const cleanItem = { ...item }; if (cleanItem.url && cleanItem.url.startsWith('data:') && cleanItem.url.length > 50000) { cleanItem.url = ''; } history.unshift(cleanItem); if (history.length > 15) { history = history.slice(0, 15); } this.persistHistory(history); } private persistHistory(history: GeneratedMedia[]): void { let list = history.map(item => { if (item.url && item.url.startsWith('data:') && item.url.length > 50000) { return { ...item, url: '' }; } return item; }); while (list.length > 0) { try { localStorage.setItem(this.MEDIA_HISTORY, JSON.stringify(list)); return; } catch (e) { list = list.map(item => (item.url && item.url.startsWith('data:') ? { ...item, url: '' } : item)); list.pop(); } } try { localStorage.removeItem(this.MEDIA_HISTORY); } catch (_) {} } clearHistory(): void { this.urlCache.clear(); try { localStorage.removeItem(this.MEDIA_HISTORY); } catch (_) {} } deleteItem(id: string): void { this.urlCache.delete(id); const history = this.getHistory().filter(item => item.id !== id); this.persistHistory(history); } }