/**
 * Print Service for Records and Attachments
 * Handles printing of record documents and their attachments with user options
 * Merges PDFs into a single document before printing using pdf-lib
 * Converts DOC/EXCEL files to PDF before merging
 */

import { PDFDocument } from 'pdf-lib';

export interface PrintOptions {
  includeRecord: boolean;
  includeAttachments: boolean;
  attachmentIndices?: number[];
}

export interface AttachmentFile {
  id: string;
  name: string;
  url: string;
  fileType: string;
  size: number;
}

/**
 * Checks if file type needs conversion to PDF
 */
const needsConversion = (fileType: string): boolean => {
  const convertibleTypes = [
    'application/msword', // .doc
    'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // .docx
    'application/vnd.ms-excel', // .xls
    'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx
    'application/vnd.ms-powerpoint', // .ppt
    'application/vnd.openxmlformats-officedocument.presentationml.presentation', // .pptx
  ];
  return convertibleTypes.some(type => fileType.includes(type) || fileType.includes(type.split('/')[1]));
};

/**
 * Converts DOC/EXCEL/PPT files to PDF using backend API
 */
const convertToPdf = async (blob: Blob, fileName: string): Promise<Blob> => {
 
  
  try {
    const formData = new FormData();
    formData.append('file', blob, fileName);

    const response = await fetch('/api/convert-to-pdf', {
      method: 'POST',
      body: formData,
    });

    if (!response.ok) {
      throw new Error(`Conversion failed with status: ${response.status}`);
    }

    const pdfBlob = await response.blob();
    return pdfBlob;
  } catch (error) {
    console.error("[PrintService] Error converting file to PDF:", fileName, error);
    // If conversion fails, return original blob and let merge handle it
    return blob;
  }
};

/**
 * Fetches a file from URL and returns as blob
 */
const fetchFileAsBlob = async (url: string, fileName: string): Promise<Blob> => {
  const response = await fetch(url);
  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }
  const blob = await response.blob();
  return blob;
};

/**
 * Converts blob to ArrayBuffer
 */
const blobToArrayBuffer = (blob: Blob): Promise<ArrayBuffer> => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onloadend = () => resolve(reader.result as ArrayBuffer);
    reader.onerror = reject;
    reader.readAsArrayBuffer(blob);
  });
};

/**
 * Merges multiple PDF blobs into a single PDF
 */
const mergePdfBlobs = async (
  pdfBlobs: { blob: Blob; name: string }[]
): Promise<Blob> => {
  try {
    const mergedPdf = await PDFDocument.create();

    for (const { blob, name } of pdfBlobs) {
      try {
        const arrayBuffer = await blobToArrayBuffer(blob);
        const pdf = await PDFDocument.load(arrayBuffer);
        const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());
        copiedPages.forEach((page: any) => mergedPdf.addPage(page));
      } catch (error) {
        console.error("[PrintService] Error adding PDF:", name, error);
      }
    }

    const mergedPdfBytes = await mergedPdf.save();
    const mergedBlob = new Blob([new Uint8Array(mergedPdfBytes)], { type: 'application/pdf' });
    
    return mergedBlob;
  } catch (error) {
    console.error("[PrintService] Error merging PDFs:", error);
    throw new Error("Failed to merge PDFs");
  }
};

/**
 * Opens a file blob in a print window
 */
const openPrintWindow = async (blob: Blob, fileName: string): Promise<void> => {
  try {
    const blobUrl = URL.createObjectURL(blob);
    
    const printWindow = window.open(blobUrl, "_blank");
    
    if (printWindow) {
      printWindow.addEventListener("load", () => {
        setTimeout(() => {
          printWindow.print();
        }, 500);
      });
      
      // Fallback: if load event doesn't fire, print anyway after delay
      setTimeout(() => {
        if (printWindow && !printWindow.closed) {
          printWindow.print();
        }
      }, 2000);
    } else {
      console.warn("[PrintService] Failed to open print window for:", fileName);
    }
  } catch (error) {
    console.error("[PrintService] Error opening print window for:", fileName, error);
    throw error;
  }
};

/**
 * Generates a combined print job for record and attachments
 * Converts DOC/EXCEL files to PDF, then merges all PDFs into a single document before printing
 */
export const printRecordWithAttachments = async (
  pdfUrl: string,
  attachments: AttachmentFile[],
  options: PrintOptions
) => {
  try {
    const pdfBlobs: { blob: Blob; name: string }[] = [];

    // Fetch record PDF if selected
    if (options.includeRecord && pdfUrl) {
      try {
        const recordBlob = await fetchFileAsBlob(pdfUrl, "Record Document");
        pdfBlobs.push({
          blob: recordBlob,
          name: "Record Document"
        });
      } catch (error) {
        console.error("[PrintService] Error fetching record PDF:", error);
      }
    }

    // Fetch selected attachments and convert if needed
    if (options.includeAttachments && attachments.length > 0) {
      const selectedAttachments = options.attachmentIndices
        ? attachments.filter((_, idx) => options.attachmentIndices?.includes(idx))
        : attachments;

      for (const attachment of selectedAttachments) {
        try {
          let attachmentBlob = await fetchFileAsBlob(attachment.url, attachment.name);
          
          // Convert to PDF if needed
          if (needsConversion(attachment.fileType)) {
            attachmentBlob = await convertToPdf(attachmentBlob, attachment.name);
          }
          
          pdfBlobs.push({
            blob: attachmentBlob,
            name: attachment.name
          });
        } catch (error) {
          console.error("[PrintService] Error processing attachment:", attachment.name, error);
        }
      }
    }

    if (pdfBlobs.length === 0) {
      throw new Error("No PDFs to print");
    }

    // Merge all PDFs
    const mergedBlob = await mergePdfBlobs(pdfBlobs);
    
    // Open merged PDF in print window
    await openPrintWindow(mergedBlob, "Merged Document");
  } catch (error) {
    console.error("[PrintService] Error in print operation:", error);
    throw error;
  }
};

/**
 * Validates print options
 */
export const validatePrintOptions = (options: PrintOptions): boolean => {
  const isValid = options.includeRecord || options.includeAttachments;
  return isValid;
};
