"use client";

// Antrian offline sederhana berbasis IndexedDB untuk aksi kurir (update status
// & upload foto) saat sinyal hilang (Bagian 8 & SOP 10.C.2).
// Foto disimpan sebagai data URL di sini sampai berhasil di-flush ke backend.
//
// Cara pakai:
//   await enqueue({ url: `/api/deliveries/${id}/proof`, method: "POST", body });
//   window.addEventListener("online", () => flushQueue());

const DB = "telur-offline";
const STORE = "queue";

function open(): Promise<IDBDatabase> {
  return new Promise((res, rej) => {
    const r = indexedDB.open(DB, 1);
    r.onupgradeneeded = () => r.result.createObjectStore(STORE, { keyPath: "id", autoIncrement: true });
    r.onsuccess = () => res(r.result);
    r.onerror = () => rej(r.error);
  });
}

export interface QueuedRequest {
  url: string;
  method: string;
  body: unknown;
  createdAt: number;
}

export async function enqueue(req: Omit<QueuedRequest, "createdAt">) {
  const db = await open();
  return new Promise<void>((res, rej) => {
    const tx = db.transaction(STORE, "readwrite");
    tx.objectStore(STORE).add({ ...req, createdAt: Date.now() });
    tx.oncomplete = () => res();
    tx.onerror = () => rej(tx.error);
  });
}

export async function pendingCount(): Promise<number> {
  const db = await open();
  return new Promise((res) => {
    const tx = db.transaction(STORE, "readonly");
    const c = tx.objectStore(STORE).count();
    c.onsuccess = () => res(c.result);
  });
}

// Kirim ulang semua request yang tertunda; hapus yang sukses.
export async function flushQueue(): Promise<{ sent: number; failed: number }> {
  const db = await open();
  const all: (QueuedRequest & { id: number })[] = await new Promise((res) => {
    const tx = db.transaction(STORE, "readonly");
    const rq = tx.objectStore(STORE).getAll();
    rq.onsuccess = () => res(rq.result as any);
  });

  let sent = 0, failed = 0;
  for (const item of all) {
    try {
      const res = await fetch(item.url, {
        method: item.method,
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ ...(item.body as object), uploadedOffline: true }),
      });
      if (!res.ok) throw new Error();
      await new Promise<void>((r) => {
        const tx = db.transaction(STORE, "readwrite");
        tx.objectStore(STORE).delete(item.id);
        tx.oncomplete = () => r();
      });
      sent++;
    } catch {
      failed++;
    }
  }
  return { sent, failed };
}
