// Mozilla pdf.js integration for PDF rendering
// Procedural style: Functions, not classes

import * as pdfjsLib from "pdfjs-dist";

// ============================================================
// PDF.js Configuration
// ============================================================

export function configurePDFJS(): void {
  pdfjsLib.GlobalWorkerOptions.workerSrc = "/static/js/pdf.worker.min.mjs";
  pdfjsLib.GlobalWorkerOptions.standardFontDataUrl = "/static/standard_fonts/";
  pdfjsLib.GlobalWorkerOptions.cMapUrl = "/static/cmaps/";
  pdfjsLib.GlobalWorkerOptions.cMapPacked = true;
}

// ============================================================
// PDF Document State
// ============================================================

interface PDFDocumentState {
  doc: pdfjsLib.PDFDocumentProxy | null;
  pages: Map<number, pdfjsLib.PDFPageProxy>;
  metadata: PDFMetadata | null;
}

interface PDFMetadata {
  title: string;
  author: string;
  subject?: string;
  keywords?: string;
  creator?: string;
  producer?: string;
  creationDate?: Date;
  modificationDate?: Date;
  pageCount: number;
}

let pdfState: PDFDocumentState = {
  doc: null,
  pages: new Map(),
  metadata: null,
};

// ============================================================
// Document Loading
// ============================================================

export async function loadPDFDocument(pdfBlob: Blob): Promise<PDFMetadata> {
  // Cleanup previous document
  unloadPDFDocument();

  const arrayBuffer = await pdfBlob.arrayBuffer();
  const loadingTask = pdfjsLib.getDocument({
    data: arrayBuffer,
  });

  pdfState.doc = await loadingTask.promise;

  // Extract metadata
  const metadata = await pdfState.doc.getMetadata().catch(() => null);
  const info = metadata?.info || {};

  pdfState.metadata = {
    title: info.Title || "Untitled",
    author: info.Author || "Unknown",
    subject: info.Subject,
    keywords: info.Keywords,
    creator: info.Creator,
    producer: info.Producer,
    creationDate: info.CreationDate ? new Date(info.CreationDate) : undefined,
    modificationDate: info.ModDate ? new Date(info.ModDate) : undefined,
    pageCount: pdfState.doc.numPages,
  };

  return pdfState.metadata;
}

export async function getPDFPage(
  pageNumber: number,
): Promise<pdfjsLib.PDFPageProxy> {
  if (!pdfState.doc) {
    throw new Error("PDF document not loaded");
  }

  // Check cache
  if (pdfState.pages.has(pageNumber)) {
    return pdfState.pages.get(pageNumber)!;
  }

  // Load page
  const page = await pdfState.doc.getPage(pageNumber);
  pdfState.pages.set(pageNumber, page);

  return page;
}

// ============================================================
// Reader Initialization
// ============================================================
interface ReaderMetadata {
  media_item_id: string;
  title: string;
  author: string;
  cover_image_path: string;
  library_type: "ebook" | "comic" | "manga" | "pdf";
  mime_type: string;
  file_path: string;
  total_pages?: number;
}
interface PDFReader {
  type: "pdf";
  doc: any;
  currentPage: number;
}
export async function initializePDFReader(
  metadata: ReaderMetadata,
): Promise<PDFReader> {
  configurePDFJS();
  const response = await fetch(metadata.file_path);
  const pdfBlob = await response.blob();
  const pdfMetadata = await loadPDFDocument(pdfBlob);
  return {
    type: "pdf",
    doc: pdfState.doc,
    currentPage: 1,
  };
}

export async function getPDFPageText(pageNumber: number): Promise<any> {
  const page = await getPDFPage(pageNumber);
  return await page.getTextContent();
}

export function getPDFMetadata(): PDFMetadata | null {
  return pdfState.metadata;
}

export function getPDFPageCount(): number {
  return pdfState.doc?.numPages || 0;
}

export function unloadPDFDocument(): void {
  pdfState.pages.clear();
  pdfState.doc = null;
  pdfState.metadata = null;
}

export function unloadPDFPage(pageNumber: number): void {
  pdfState.pages.delete(pageNumber);
}
