(function initFivaPdfParser(global) {
  "use strict";

  const LOG = "[FIVA]";
  let pdfJsPromise = null;

  async function loadPdfJs() {
    if (!pdfJsPromise) {
      pdfJsPromise = import(chrome.runtime.getURL("fiva/vendor/pdfjs/pdf.min.mjs"))
        .then((pdfjsLib) => {
          pdfjsLib.GlobalWorkerOptions.workerSrc = chrome.runtime.getURL("fiva/vendor/pdfjs/pdf.worker.min.mjs");
          return pdfjsLib;
        });
    }
    return pdfJsPromise;
  }

  function cloneBuffer(arrayBuffer) {
    return arrayBuffer.slice(0);
  }

  async function loadDocument(arrayBuffer) {
    const pdfjsLib = await loadPdfJs();
    return pdfjsLib.getDocument({ data: cloneBuffer(arrayBuffer) }).promise;
  }

  function pageTextFromItems(items = []) {
    const rows = [];

    items.forEach((item) => {
      const text = String(item.str || "").trim();
      if (!text) return;
      const transform = item.transform || [];
      const x = Number(transform[4] || 0);
      const y = Number(transform[5] || 0);
      let row = rows.find((entry) => Math.abs(entry.y - y) <= 3);
      if (!row) {
        row = { y, items: [] };
        rows.push(row);
      }
      row.items.push({ x, text });
    });

    return rows
      .sort((left, right) => right.y - left.y)
      .map((row) => row.items
        .sort((left, right) => left.x - right.x)
        .map((item) => item.text)
        .join(" ")
        .replace(/[ \t]+/g, " ")
        .trim())
      .filter(Boolean)
      .join("\n");
  }

  async function extractText(arrayBuffer) {
    const pdf = await loadDocument(arrayBuffer);
    const pages = [];

    for (let pageNumber = 1; pageNumber <= pdf.numPages; pageNumber += 1) {
      const page = await pdf.getPage(pageNumber);
      const content = await page.getTextContent();
      const text = pageTextFromItems(content.items);
      if (text) pages.push(text);
    }

    await pdf.destroy?.();
    console.log(LOG, "PDF parsed successfully");
    return {
      text: pages.join("\n"),
      pageCount: pdf.numPages,
      confidence: pages.join(" ").trim().length > 80 ? 90 : 45
    };
  }

  async function renderPages(arrayBuffer, options = {}) {
    const maxPages = Math.max(1, Math.min(Number(options.maxPages || 2), 4));
    const scale = Math.max(1, Math.min(Number(options.scale || 1.65), 2.5));
    const pdf = await loadDocument(arrayBuffer);
    const images = [];

    for (let pageNumber = 1; pageNumber <= Math.min(pdf.numPages, maxPages); pageNumber += 1) {
      const page = await pdf.getPage(pageNumber);
      const viewport = page.getViewport({ scale });
      const canvas = document.createElement("canvas");
      const context = canvas.getContext("2d", { alpha: false });
      canvas.width = Math.ceil(viewport.width);
      canvas.height = Math.ceil(viewport.height);
      await page.render({ canvasContext: context, viewport }).promise;
      images.push(canvas.toDataURL("image/png"));
    }

    await pdf.destroy?.();
    return images;
  }

  const PdfParser = Object.freeze({
    extractText,
    renderPages
  });

  global.FIVA = Object.assign(global.FIVA || {}, { PdfParser });
})(typeof globalThis !== "undefined" ? globalThis : this);
