import * as pdfjsLib from 'pdfjs-dist/webpack.mjs';

const ensureUint8Array = (buffer) => {
  if (buffer instanceof Uint8Array) {
    return buffer;
  }

  return new Uint8Array(buffer);
};

/**
 *
 * @param {ArrayBuffer|Uint8Array|Buffer} pdfBuffer
 * @param {object} options
 * @param {number} options.maxPages
 * @param {boolean} options.includeMetadata
 * @returns {Promise<object>}
 */
export const parsePdfBuffer = async (pdfBuffer, options = {}) => {
  const {
    maxPages = null,
    includeMetadata = false,
  } = options;

  const pdfData = ensureUint8Array(pdfBuffer);
  const loadingTask = pdfjsLib.getDocument({
    data: pdfData,
  });

  const pdfDocument = await loadingTask.promise;
  const numPages = pdfDocument.numPages;
  let pagesToParse = numPages;

  if (maxPages !== null) {
    if (maxPages < numPages) {
      pagesToParse = maxPages;
    }
  }

  const textPages = [];
  let metadata = null;

  if (includeMetadata === true) {
    const metadataResult = await pdfDocument.getMetadata();

    metadata = {
      title: metadataResult.info?.Title || null,
      author: metadataResult.info?.Author || null,
      subject: metadataResult.info?.Subject || null,
      creator: metadataResult.info?.Creator || null,
      producer: metadataResult.info?.Producer || null,
      creationDate: metadataResult.info?.CreationDate || null,
      modificationDate: metadataResult.info?.ModDate || null,
    };
  }

  for (let pageNum = 1; pageNum <= pagesToParse; pageNum++) {
    const page = await pdfDocument.getPage(pageNum);
    const textContent = await page.getTextContent();
    const pageText = textContent.items
      .map((item) => item.str)
      .join(' ');

    textPages.push({
      pageNumber: pageNum,
      text: pageText,
    });
  }

  const fullText = textPages.map((page) => page.text).join('\n\n');

  return {
    text: fullText,
    pages: textPages,
    totalPages: numPages,
    parsedPages: pagesToParse,
    metadata,
  };
};

/**
 *
 * @param {ArrayBuffer|Uint8Array|Buffer} pdfBuffer
 * @param {number} maxPages
 * @returns {Promise<string>}
 */
export const parsePdfToText = async (pdfBuffer, maxPages = null) => {
  const result = await parsePdfBuffer(pdfBuffer, {
    maxPages,
    includeMetadata: false,
  });

  return result.text;
};

/**
 *
 * @param {ArrayBuffer|Uint8Array|Buffer} pdfBuffer
 * @param {number} pageNumber
 * @returns {Promise<string>}
 */
export const parsePdfPageToText = async (pdfBuffer, pageNumber) => {
  const pdfData = ensureUint8Array(pdfBuffer);
  const loadingTask = pdfjsLib.getDocument({
    data: pdfData,
  });

  const pdfDocument = await loadingTask.promise;

  const page = await pdfDocument.getPage(pageNumber);
  const textContent = await page.getTextContent();
  const pageText = textContent.items
    .map((item) => item.str)
    .join(' ');

  return pageText;
};
