import { ref, readonly } from 'vue' import type { AlbionPriceEntry, AlbionCity, ManualPriceEntry, ManualPriceCache } from '../types/api' // ─── Override duration ──────────────────────────────────────────────────────── export const OVERRIDE_DURATION_OPTIONS: { label: string; ms: number }[] = [ { label: '30 min', ms: 30 * 60 * 1000 }, { label: '1 hour', ms: 60 * 60 * 1000 }, { label: '2 hours', ms: 2 * 60 * 60 * 1000 }, { label: '4 hours', ms: 4 * 60 * 60 * 1000 }, { label: '8 hours', ms: 8 * 60 * 60 * 1000 }, { label: '24 hours',ms: 24 * 60 * 60 * 1000 }, ] const DURATION_STORAGE_KEY = 'albion-override-duration' const MANUAL_STORAGE_KEY = 'albion-manual-prices' function loadOverrideDuration(): number { try { const raw = localStorage.getItem(DURATION_STORAGE_KEY) if (raw) { const ms = Number(raw) if (OVERRIDE_DURATION_OPTIONS.some(o => o.ms === ms)) return ms } } catch { /* ignore */ } return 24 * 60 * 60 * 1000 // default 24 hours } function loadManualPricesFromStorage(): ManualPriceCache { try { const raw = localStorage.getItem(MANUAL_STORAGE_KEY) if (raw) { const obj = JSON.parse(raw) as Record return new Map(Object.entries(obj)) } } catch { /* ignore */ } return new Map() } function saveManualPricesToStorage(map: ManualPriceCache): void { try { const obj: Record = {} for (const [key, val] of map) obj[key] = val localStorage.setItem(MANUAL_STORAGE_KEY, JSON.stringify(obj)) } catch { /* ignore */ } } // ─── Module-level singleton state ──────────────────────────────────────────── const manualPrices = ref(loadManualPricesFromStorage()) const overrideDurationMs = ref(loadOverrideDuration()) // ─── Helpers ────────────────────────────────────────────────────────────────── function cacheKey(itemId: string, city: string): string { return `${itemId}::${city}` } function isManualExpired(entry: ManualPriceEntry): boolean { return Date.now() - new Date(entry.editedAt).getTime() > overrideDurationMs.value } function synthesizeManualEntry( entry: ManualPriceEntry, itemId: string, city: AlbionCity, ): AlbionPriceEntry { return { item_id: itemId, city, quality: 1, sell_price_min: entry.sell_price_min, sell_price_min_date: entry.editedAt, sell_price_max: entry.sell_price_min, buy_price_min: 0, buy_price_max: 0, } } // ─── Price accessors ────────────────────────────────────────────────────────── function getPrice(itemId: string, city: AlbionCity): AlbionPriceEntry | null { const key = cacheKey(itemId, city) const manual = manualPrices.value.get(key) if (manual && !isManualExpired(manual)) { return synthesizeManualEntry(manual, itemId, city) } return null } // ─── Manual price management ────────────────────────────────────────────────── function setManualPrice(itemId: string, city: AlbionCity, price: number): void { const key = cacheKey(itemId, city) const next = new Map(manualPrices.value) next.set(key, { sell_price_min: price, editedAt: new Date().toISOString() }) manualPrices.value = next saveManualPricesToStorage(next) } function clearManualPrice(itemId: string, city: AlbionCity): void { const key = cacheKey(itemId, city) if (!manualPrices.value.has(key)) return const next = new Map(manualPrices.value) next.delete(key) manualPrices.value = next saveManualPricesToStorage(next) } function isManualPrice(itemId: string, city: AlbionCity): boolean { const entry = manualPrices.value.get(cacheKey(itemId, city)) return !!entry && !isManualExpired(entry) } function getManualEntry(itemId: string, city: AlbionCity): ManualPriceEntry | undefined { const entry = manualPrices.value.get(cacheKey(itemId, city)) return entry && !isManualExpired(entry) ? entry : undefined } function setOverrideDuration(ms: number): void { overrideDurationMs.value = ms try { localStorage.setItem(DURATION_STORAGE_KEY, String(ms)) } catch { /* ignore */ } } // ─── Public API ─────────────────────────────────────────────────────────────── export function useAlbionPrices() { return { overrideDurationMs: readonly(overrideDurationMs), getPrice, setManualPrice, clearManualPrice, isManualPrice, getManualEntry, setOverrideDuration, } }