"use client";

import { enqueuePendingAction, getPendingActions, deletePendingAction, type PendingAction } from "@/lib/offline-db";

type ServiceWorkerRegistrationWithSync = ServiceWorkerRegistration & {
  sync?: { register: (tag: string) => Promise<void> };
};

export const SYNC_TAG = "epicure-sync";

/** Queues a mutation that failed because the browser is offline. Tries to
 * register a Background Sync so the service worker replays it as soon as
 * connectivity returns (Chromium only); Safari/Firefox fall back to the
 * "online" event listener in OfflineSyncManager. */
export async function queueOfflineAction(action: { method: string; url: string; body: unknown; description: string }): Promise<void> {
  await enqueuePendingAction(action);
  if ("serviceWorker" in navigator) {
    try {
      const registration = (await navigator.serviceWorker.ready) as ServiceWorkerRegistrationWithSync;
      await registration.sync?.register(SYNC_TAG);
    } catch {
      // Background Sync unsupported or registration failed — the
      // online-event fallback in OfflineSyncManager still covers this.
    }
  }
}

/** Replays queued actions in the order they were created, stopping at the
 * first failure so a dependent later action (e.g. add-items-to-a-just-
 * created-list) never runs ahead of the one it depends on. Returns how many
 * actions succeeded. Mirrors the service worker's own replay logic in
 * public/sw.js — kept for browsers with no Background Sync support. */
export async function flushOfflineQueue(): Promise<number> {
  const pending = await getPendingActions();
  let synced = 0;
  for (const action of pending) {
    const ok = await replayAction(action);
    if (!ok) break;
    await deletePendingAction(action.id);
    synced += 1;
  }
  return synced;
}

async function replayAction(action: PendingAction): Promise<boolean> {
  try {
    const res = await fetch(action.url, {
      method: action.method,
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(action.body),
    });
    return res.ok;
  } catch {
    return false;
  }
}
