// Armazena os arquivos GLB recentes (após conversão) para reuso rápido,
// sem necessidade de recarregar da nuvem ou do disco local.
//
// Estratégia:
//  - Metadados (lista JSON ordenada) em localStorage  → leitura síncrona / rápida
//  - Blob real do GLB em IndexedDB                    → suporta arquivos grandes

const META_KEY = 'tsxr_recent_files_v1';
const DB_NAME = 'tsxr-recent';
const STORE = 'glb';
const MAX_RECENTS = 6;

export interface RecentFileMeta {
  id: string;          // chave no IndexedDB
  fileName: string;    // nome do arquivo GLB
  fileSize: number;    // bytes
  addedAt: number;     // timestamp ms
}

// ── IndexedDB helpers ─────────────────────────────────────────────
function openDB(): Promise<IDBDatabase> {
  return new Promise((resolve, reject) => {
    const req = indexedDB.open(DB_NAME, 1);
    req.onupgradeneeded = () => {
      const db = req.result;
      if (!db.objectStoreNames.contains(STORE)) db.createObjectStore(STORE);
    };
    req.onsuccess = () => resolve(req.result);
    req.onerror = () => reject(req.error);
  });
}

async function idbPut(id: string, blob: Blob): Promise<void> {
  const db = await openDB();
  await new Promise<void>((resolve, reject) => {
    const tx = db.transaction(STORE, 'readwrite');
    tx.objectStore(STORE).put(blob, id);
    tx.oncomplete = () => resolve();
    tx.onerror = () => reject(tx.error);
  });
  db.close();
}

async function idbGet(id: string): Promise<Blob | undefined> {
  const db = await openDB();
  const blob = await new Promise<Blob | undefined>((resolve, reject) => {
    const tx = db.transaction(STORE, 'readonly');
    const req = tx.objectStore(STORE).get(id);
    req.onsuccess = () => resolve(req.result as Blob | undefined);
    req.onerror = () => reject(req.error);
  });
  db.close();
  return blob;
}

async function idbDelete(id: string): Promise<void> {
  const db = await openDB();
  await new Promise<void>((resolve, reject) => {
    const tx = db.transaction(STORE, 'readwrite');
    tx.objectStore(STORE).delete(id);
    tx.oncomplete = () => resolve();
    tx.onerror = () => reject(tx.error);
  });
  db.close();
}

// ── Metadata helpers ─────────────────────────────────────────────
export function listRecentFiles(): RecentFileMeta[] {
  try {
    const raw = localStorage.getItem(META_KEY);
    if (!raw) return [];
    const parsed = JSON.parse(raw) as RecentFileMeta[];
    return Array.isArray(parsed) ? parsed : [];
  } catch {
    return [];
  }
}

function saveMeta(list: RecentFileMeta[]) {
  try { localStorage.setItem(META_KEY, JSON.stringify(list)); } catch {}
}

/** Registra um GLB nos recentes (substitui se mesmo fileName) e mantém apenas MAX_RECENTS. */
export async function addRecentFile(fileName: string, blob: Blob): Promise<void> {
  try {
    const list = listRecentFiles();
    const existing = list.find(r => r.fileName === fileName);
    const id = existing?.id ?? `rf_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 6)}`;
    await idbPut(id, blob);
    const filtered = list.filter(r => r.fileName !== fileName);
    const next: RecentFileMeta[] = [
      { id, fileName, fileSize: blob.size, addedAt: Date.now() },
      ...filtered,
    ].slice(0, MAX_RECENTS);
    // Limpa blobs removidos
    for (const r of filtered.slice(MAX_RECENTS - 1)) {
      try { await idbDelete(r.id); } catch {}
    }
    saveMeta(next);
  } catch (e) {
    console.warn('[recentFiles] addRecent failed', e);
  }
}

/** Recupera o blob de um recente e devolve um object URL pronto para uso. */
export async function loadRecentFile(id: string): Promise<{ url: string; blob: Blob } | null> {
  const blob = await idbGet(id);
  if (!blob) return null;
  return { url: URL.createObjectURL(blob), blob };
}

export async function removeRecentFile(id: string): Promise<void> {
  const list = listRecentFiles().filter(r => r.id !== id);
  saveMeta(list);
  try { await idbDelete(id); } catch {}
}

export async function clearRecentFiles(): Promise<void> {
  const list = listRecentFiles();
  for (const r of list) { try { await idbDelete(r.id); } catch {} }
  saveMeta([]);
}
