import moment from 'moment';
import asyncRetry from 'async-retry';
import { loggerBackground } from '@/plugins/logger';
import { uploadS3OrderPrintPdf } from '@/api/autoshopee/service/s3';
import { parsePdfData } from '@/api/autoshopee/service/pdf';

export const RETRY_PRINT_PDF = {
  retries: 5,
  factor: 1,
  minTimeout: 5000,
  maxTimeout: 5000,
};

/**
 * @param {string} html
 * @param {Record<string, RegExp>} regexPatterns
 * @returns {string[]}
 */
export const extractOrderIdFromHtml = (html, regexPatterns) => {
  const text = html
    .replace(/<script[\s\S]*?<\/script>/gi, ' ')
    .replace(/<style[\s\S]*?<\/style>/gi, ' ')
    .replace(/<[^>]+>/g, ' ')
    .replace(/\s+/g, ' ')
    .trim();

  const codes = Object.values(regexPatterns).reduce((acc, regex) => {
    const found = [...text.matchAll(regex)].map((m) => m[0]);
    acc.push(...found);
    return acc;
  }, []);

  return Array.from(new Set(codes));
};

/**
 * @param {string} printId
 * @param {string} shopId
 * @param {string} shopName
 * @param {string} platform
 * @param {ModelApiLoader} OrderPdfPrintJobModel
 * @param {() => Promise<ArrayBuffer>} getPdfBuffer
 * @param {Record<string, RegExp>} regexPatterns
 * @returns {Promise<OrderPdfBucket>}
 */
export const saveLogPrintJob = async (
  printId,
  shopId,
  shopName,
  platform,
  OrderPdfPrintJobModel,
  getPdfBuffer,
  regexPatterns,
) => {
  if (!shopId) {
    return null;
  }

  if (!printId) {
    return null;
  }

  /** @type {OrderPdfBucket} */
  const getPrintJob = await OrderPdfPrintJobModel.getId(printId);

  if (getPrintJob) {
    return getPrintJob;
  }

  const datePrint = moment().format('YYYY-MM-DD');

  /** @type {OrderPdfBucket} */
  const payloadSave = {
    shopId: shopId.toString(),
    shopName: (shopName || shopId).toString(),
    printId,
    type: 'pdf',
    platform,
  };

  try {
    const pdfBuffer = await asyncRetry(async () => {
      const getBuffer = await getPdfBuffer();

      if (getBuffer.byteLength <= 5 * 1024) {
        throw new Error('PDF_BUFFER_TOO_SMALL');
      }

      return getBuffer;
    }, RETRY_PRINT_PDF);

    payloadSave.size = pdfBuffer.byteLength;

    try {
      const { html, text, page } = await parsePdfData(pdfBuffer);
      payloadSave.search = extractOrderIdFromHtml(html, regexPatterns).join(',');
      payloadSave.text = text;
      payloadSave.page = page || 1;
    } catch (error) {
      loggerBackground.error({
        msg: 'PRINT_PDF_INFO_ERROR',
        platform,
        error,
      });
    }

    try {
      const fileName = `${printId}.pdf`;
      const filePath = `${platform}/${datePrint}/${shopId}/${fileName}`;

      const uploadS3 = await uploadS3OrderPrintPdf(pdfBuffer, filePath);

      payloadSave.s3Path = filePath;
      payloadSave.s3Id = uploadS3.fileId;
      payloadSave.s3Url = uploadS3.fileUrl;
    } catch (error) {
      loggerBackground.error({
        msg: 'PRINT_PDF_S3_ERROR',
        platform,
        error,
      });
    }
  } catch (error) {
    loggerBackground.error({
      msg: 'PRINT_PDF_DOWNLOAD_ERROR',
      platform,
      error,
    });
  }

  if (!payloadSave.s3Path) {
    return null;
  }

  return OrderPdfPrintJobModel.insert(payloadSave, printId);
};
