/**
 * Persistent caching for the self-hosted @imgly model + wasm assets.
 *
 * @imgly/background-removal fetches its assets with plain `fetch`, so whether
 * they persist between runs is at the mercy of the server's Cache-Control
 * headers. The Vite dev server (and some hosts) send `no-store`/`no-cache`,
 * which makes the model re-download on every run.
 *
 * To make caching deterministic and host-independent, we intercept same-origin
 * `/imgly/` requests and back them with the Cache Storage API, which we control
 * explicitly. CacheStorage is shared across the origin, so an asset cached by
 * the worker (during a run) is visible to the main thread (for the pre-run
 * download estimate) and vice-versa.
 */
export const IMGLY_CACHE_NAME = "plimi-imgly-v1";

type FetchInput = Parameters<typeof fetch>[0];

function urlOf(input: FetchInput): string {
  if (typeof input === "string") return input;
  if (input instanceof URL) return input.toString();
  return input.url;
}

function isImglyUrl(url: string): boolean {
  return url.includes("/imgly/");
}

let installed = false;

/** Route `/imgly/` fetches through Cache Storage. Safe to call multiple times. */
export function installImglyCache(): void {
  if (installed) return;
  installed = true;

  const scope = self as unknown as {
    fetch: typeof fetch;
    caches?: CacheStorage;
  };
  if (!scope.caches || typeof scope.fetch !== "function") return;

  const original = scope.fetch.bind(scope);
  scope.fetch = async (input: FetchInput, init?: RequestInit) => {
    try {
      const url = urlOf(input);
      if (isImglyUrl(url)) {
        const cache = await scope.caches!.open(IMGLY_CACHE_NAME);
        const hit = await cache.match(url);
        if (hit) return hit;
        const res = await original(input, init);
        if (res.ok) {
          try {
            await cache.put(url, res.clone());
          } catch {
            // Quota or opaque response — fall through with the live response.
          }
        }
        return res;
      }
    } catch {
      // Any cache failure: fall back to the network below.
    }
    return original(input, init);
  };
}

/** Whether an `/imgly/` asset is already stored locally (no download needed). */
export async function isImglyAssetCached(url: string): Promise<boolean> {
  const scope = self as unknown as { caches?: CacheStorage };
  if (scope.caches) {
    try {
      const cache = await scope.caches.open(IMGLY_CACHE_NAME);
      return Boolean(await cache.match(url));
    } catch {
      // fall through to HTTP-cache probe
    }
  }
  try {
    const res = await fetch(url, { cache: "only-if-cached", mode: "same-origin" });
    return res.ok;
  } catch {
    return false;
  }
}

/** Delete all persisted IMG.LY model and runtime assets for this origin. */
export async function clearImglyCache(): Promise<boolean> {
  const scope = globalThis as typeof globalThis & { caches?: CacheStorage };
  if (!scope.caches) return false;
  return scope.caches.delete(IMGLY_CACHE_NAME);
}
