import { describe, expect, test } from "bun:test";
import {
  createOfflineQueue,
  createWebManifest,
  generateServiceWorker,
  memoryOfflineQueueStore,
  pwaClientRuntime,
  resolveOfflineConflict,
} from "../src/index.ts";
describe("PWA platform", () => {
  test("generates manifest, caching, sync and push", () => {
    expect(createWebManifest({ name: "Field App" })).toMatchObject({
      name: "Field App",
      display: "standalone",
      start_url: "/",
    });
    const source = generateServiceWorker({ offlineUrl: "/offline", cacheUrls: ["/app.css"] });
    expect(source).toContain("wrnexus:background-sync");
    expect(source).toContain("notificationclick");
    expect(source).toContain("const SAME_ORIGIN_ONLY=true");
    expect(source).toContain("new URL(event.request.url).origin!==self.location.origin");
    expect(
      generateServiceWorker({
        runtimeCaching: [{ pattern: "^https://cdn.example.com/", strategy: "cache-first" }],
      }),
    ).toContain("const SAME_ORIGIN_ONLY=false");
    expect(pwaClientRuntime()).toContain("wrnexus:pwa-installable");
  });
  test("queues, retries and removes successful mutations", async () => {
    let available = false;
    const store = memoryOfflineQueueStore();
    const queue = createOfflineQueue({
      store,
      now: () => 10,
      fetch: async () => (available ? new Response("ok") : Promise.reject(new Error("offline"))),
    });
    await queue.enqueue({
      endpoint: "https://example.test/forms",
      method: "POST",
      payload: { name: "A" },
    });
    expect((await queue.sync())[0]?.ok).toBe(false);
    expect((await queue.list())[0]?.attempts).toBe(1);
    available = true;
    expect((await queue.sync())[0]?.ok).toBe(true);
    expect(await queue.list()).toEqual([]);
  });
  test("resolves conflicts", () => {
    expect(
      resolveOfflineConflict({ updatedAt: 2, value: "client" }, { updatedAt: 1, value: "server" })
        .action,
    ).toBe("client");
    expect(
      resolveOfflineConflict({ value: 1 }, { value: 2 }, (a, b) => ({ value: a.value + b.value }))
        .value,
    ).toEqual({ value: 3 });
  });
});
