import { fileApi } from "./fileApi";
import { parseContentDispositionFilename } from "./filename";

interface PreviewRequest {
  controller: AbortController;
  promise: Promise<Awaited<ReturnType<typeof fileApi.preview>>>;
  consumers: number;
}
const previewRequests = new Map<string, PreviewRequest>();

export function loadPreviewOnce(id: string) {
  const existing = previewRequests.get(id);
  if (existing) return existing.promise;
  const controller = new AbortController();
  const request: PreviewRequest = {
    controller,
    consumers: 0,
    promise: Promise.resolve(undefined as never),
  };
  request.promise = fileApi.preview(id, controller.signal).finally(() => {
    if (previewRequests.get(id) === request) previewRequests.delete(id);
  });
  previewRequests.set(id, request);
  return request.promise;
}

export function acquirePreview(id: string): {
  promise: Promise<Awaited<ReturnType<typeof fileApi.preview>>>;
  release: () => void;
} {
  const promise = loadPreviewOnce(id);
  const request = previewRequests.get(id);
  if (!request) return { promise, release: () => undefined };
  request.consumers += 1;
  let released = false;
  return {
    promise,
    release: () => {
      if (released) return;
      released = true;
      request.consumers -= 1;
      globalThis.setTimeout(() => {
        if (
          request.consumers === 0 &&
          previewRequests.get(id) === request
        ) {
          request.controller.abort();
          previewRequests.delete(id);
        }
      }, 0);
    },
  };
}

export function createPreviewUrl(blob: Blob): string {
  return URL.createObjectURL(blob);
}

export function revokeObjectUrl(url: string | null): void {
  if (url) URL.revokeObjectURL(url);
}

export async function downloadFile(
  id: string,
  fallbackName: string,
  signal?: AbortSignal,
): Promise<{ filename: string; requestId: string }> {
  const result = await fileApi.download(id, signal);
  const filename = parseContentDispositionFilename(
    result.contentDisposition,
    fallbackName,
  );
  const url = URL.createObjectURL(result.blob);
  const anchor = document.createElement("a");
  try {
    anchor.href = url;
    anchor.download = filename;
    anchor.style.display = "none";
    document.body.appendChild(anchor);
    anchor.click();
  } finally {
    anchor.remove();
    URL.revokeObjectURL(url);
  }
  return { filename, requestId: result.requestId };
}

export function clearPreviewRequestsForTests(): void {
  previewRequests.clear();
}
