package com.ffii.lioner.modules.lioner.pdf.service;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;

import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.springframework.stereotype.Service;

import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.utils.PdfMerger;

@Service
public class PdfMergeService {

    public void mergePdfs() throws IOException {
        // Load PDF A and PDF B
        String filePathA = "C:\\dev\\pdf\\pdfA.pdf";
        File fileA = new File(filePathA);

        String filePathB = "C:\\dev\\pdf\\pdfB.pdf";
        File fileB = new File(filePathB);

        String outputPath = "C:\\dev\\pdf\\pdfOut.pdf";

        try (
            PDDocument pdfA = Loader.loadPDF(fileA);
            PDDocument pdfB = Loader.loadPDF(fileB);
            
            PDDocument mergedPdf = new PDDocument()) {

            for (int i = 0; i < pdfB.getNumberOfPages(); i++) {
                PDPage page = pdfB.getPage(i);
                mergedPdf.addPage(page);
            }

            //this is for remove the password and copy the whole pdf
            //pdfB.setAllSecurityToBeRemoved(true);
            //pdfB.save(new File(outputPath));
            
            // Save the merged PDF
            mergedPdf.save(new File(outputPath));
        }
    }

    public byte[] mergePdfsItext7(String formCode, byte[] pdfABytes, byte[] pdfBBytes) throws IOException {

        // Defined constants for clarity
        final int IDA_SIG_PAGE = 11; // Page to skip for IDA
        final int FNA_SIG_PAGE = 7;  // Page to skip for FNA
        final int HSBC_REP_PAGE = 11; // Page to replace for HSBCFIN
        final int HSBCA31_REP_START = 28; // Start page to replace for HSBCA31 (Page 28)
        final int HSBCA31_REP_END = 29;   // End page to replace for HSBCA31 (Page 29)
        final int HSBCA31_REP_COUNT = 2;  // Number of pages from pdfB to insert
        
        final int MLB03S_REP_PAGE = 9;
        final int MLFNA_REP_PAGE = 4;

        final int SLFNA_REP_PAGE = 5;
        final int SLAPP_REP_PAGE = 16;
        final int SLGII_REP_PAGE = 13;

        // Use java.io.ByteArrayOutputStream
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { 
            
            PdfWriter writer = new PdfWriter(baos);
            PdfDocument mergedPdf = new PdfDocument(writer);
            PdfMerger merger = new PdfMerger(mergedPdf);

            // 1. Process PDF A (The primary document)
            try (PdfReader readerA = new PdfReader(new ByteArrayInputStream(pdfABytes));
                 PdfDocument docA = new PdfDocument(readerA)) {
                
                int totalPagesA = docA.getNumberOfPages();
                
                // --- Single Page Replacement Forms (New Logic) ---
                int repPage = -1; // Page number to be replaced in docA

                if ("MLB03S".equals(formCode)) {
                    repPage = MLB03S_REP_PAGE;
                } else if ("MLFNA_EN".equals(formCode) || "MLFNA_CHI".equals(formCode)) {
                    repPage = MLFNA_REP_PAGE;
                } else if ("SLFNA_EN".equals(formCode) || "SLFNA_CHI".equals(formCode)) {
                    repPage = SLFNA_REP_PAGE;
                } else if ("SLAPP".equals(formCode)) {
                    repPage = SLAPP_REP_PAGE;
                } else if ("SLGII".equals(formCode)) {
                    repPage = SLGII_REP_PAGE;
                }
                
                if (repPage != -1 && totalPagesA >= repPage) {
                    // This block handles all single-page replacements (repPage in docA replaced by docB page 1)
                    
                    // A. Copy pages 1 up to (repPage - 1)
                    if (repPage > 1) {
                        merger.merge(docA, 1, repPage - 1);
                    }
                    
                    // B. Insert replacement page (page 1) from PDF B (if available)
                    if (pdfBBytes != null && pdfBBytes.length > 0) {
                        try (PdfReader readerB = new PdfReader(new ByteArrayInputStream(pdfBBytes));
                             PdfDocument docB = new PdfDocument(readerB)) {
                            
                            // Copy ONLY page 1 from docB
                            merger.merge(docB, 1, 1);
                        }
                    }
                    
                    // C. Copy pages (repPage + 1) through the end
                    if (totalPagesA > repPage) {
                        merger.merge(docA, repPage + 1, totalPagesA);
                    }

                // --- Existing Logic (Skip/Multi-page Replace) ---
                } else if ("IDA".equals(formCode) && totalPagesA >= IDA_SIG_PAGE) {
                    // --- IDA: SKIP page 11, then merge rest of A ---
                    
                    // Copy pages 1 through 10 (IDA_SIG_PAGE - 1)
                    if (IDA_SIG_PAGE > 1) {
                        merger.merge(docA, 1, IDA_SIG_PAGE - 1);
                    }
                    // Copy pages 12 through the end (IDA_SIG_PAGE + 1)
                    if (totalPagesA > IDA_SIG_PAGE) {
                        merger.merge(docA, IDA_SIG_PAGE + 1, totalPagesA);
                    }
                    
                } else if ("FNA".equals(formCode) && totalPagesA >= FNA_SIG_PAGE) {
                    // --- FNA: SKIP page 7, then merge rest of A ---
                    
                    // Copy pages 1 through 6 (FNA_SIG_PAGE - 1)
                    if (FNA_SIG_PAGE > 1) {
                        merger.merge(docA, 1, FNA_SIG_PAGE - 1);
                    }
                    // Copy pages 8 through the end (FNA_SIG_PAGE + 1)
                    if (totalPagesA > FNA_SIG_PAGE) {
                        merger.merge(docA, FNA_SIG_PAGE + 1, totalPagesA);
                    }
                    
                } else if ("HSBCFIN".equals(formCode) && totalPagesA >= HSBC_REP_PAGE) {
                    // --- HSBCFIN: REPLACE page 11 with PDF B page 1 (Similar to new logic, but kept separate for history) ---
                    
                    // A. Copy pages 1 up to 10 (HSBC_REP_PAGE - 1)
                    if (HSBC_REP_PAGE > 1) {
                        merger.merge(docA, 1, HSBC_REP_PAGE - 1);
                    }
                    
                    // B. Insert replacement page from PDF B (if available)
                    if (pdfBBytes != null && pdfBBytes.length > 0) {
                        try (PdfReader readerB = new PdfReader(new ByteArrayInputStream(pdfBBytes));
                              PdfDocument docB = new PdfDocument(readerB)) {
                            
                            // Copy ONLY page 1 from docB
                            merger.merge(docB, 1, 1);
                        }
                    }
                    
                    // C. Copy pages 12 through the end (HSBC_REP_PAGE + 1)
                    if (totalPagesA > HSBC_REP_PAGE) {
                        merger.merge(docA, HSBC_REP_PAGE + 1, totalPagesA);
                    }

                } else if ("HSBCA31".equals(formCode) && totalPagesA >= HSBCA31_REP_END) {
                    // --- HSBCA31: REPLACE pages 28-29 with PDF B pages 1-2 ---

                    // A. Copy pages 1 up to 27 (HSBCA31_REP_START - 1)
                    if (HSBCA31_REP_START > 1) {
                        merger.merge(docA, 1, HSBCA31_REP_START - 1);
                    }

                    // B. Insert replacement pages (1 and 2) from PDF B (if available)
                    if (pdfBBytes != null && pdfBBytes.length > 0) {
                        try (PdfReader readerB = new PdfReader(new ByteArrayInputStream(pdfBBytes));
                             PdfDocument docB = new PdfDocument(readerB)) {
                            
                            // Copy ONLY pages 1 and 2 from docB
                            if (docB.getNumberOfPages() >= HSBCA31_REP_COUNT) {
                                merger.merge(docB, 1, HSBCA31_REP_COUNT);
                            } else {
                                // Optionally log or throw error if pdfB is too short
                            }
                        }
                    }

                    // C. Copy pages 30 through the end (HSBCA31_REP_END + 1)
                    if (totalPagesA > HSBCA31_REP_END) {
                        merger.merge(docA, HSBCA31_REP_END + 1, totalPagesA);
                    }

                } else {
                    // Default: Copy all pages from docA
                    merger.merge(docA, 1, totalPagesA);
                }
            } 
            
            // 2. Process PDF B (Only appended if IDA or FNA)
            // Note: Single-page replacement forms (MLB03S, MLFNA, etc.) are NOT appending pdfB, 
            // as pdfB page 1 was used for replacement and the requirement did not specify appending.
            if (pdfBBytes != null && pdfBBytes.length > 0) {
                if ("IDA".equals(formCode) || "FNA".equals(formCode)){
                    try (PdfReader readerB = new PdfReader(new ByteArrayInputStream(pdfBBytes));
                         PdfDocument docB = new PdfDocument(readerB)) {
                        
                        // Copy ONLY page 1 from docB to append as the last page
                        merger.merge(docB, 1, 1);
                    }
                }
            }

            // 3. Close the merged PDF document
            mergedPdf.close(); 
            
            // 4. Return the resulting byte array
            return baos.toByteArray();

        } // baos is closed here
    }

    public byte[] mergePdf2sItext7(String formCode, byte[] pdfABytes, byte[] pdfBBytes) throws IOException {

        // UPDATED CONSTANTS FOR NEW REQUIREMENTS
        final int MLB03S_REP_PAGE_A = 12;
        final int SLAPP_REP_START_A = 18;
        final int SLAPP_REP_END_A = 19; 
        final int SLAPP_REP_COUNT_B = 2;
        final int SLGII_REP_START_A = 15;
        final int SLGII_REP_END_A = 16; 
        final int SLGII_REP_COUNT_B = 2;
      
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { 
            
            PdfWriter writer = new PdfWriter(baos);
            PdfDocument mergedPdf = new PdfDocument(writer);
            PdfMerger merger = new PdfMerger(mergedPdf);

            // 1. Process PDF A (The primary document)
            try (PdfReader readerA = new PdfReader(new ByteArrayInputStream(pdfABytes));
                PdfDocument docA = new PdfDocument(readerA)) {
                    
                int totalPagesA = docA.getNumberOfPages();
                
                // --- Multi-page Replacement Forms (New/Existing Logic) ---
                int repStartA = -1; // Start page in docA to replace
                int repEndA = -1;   // End page in docA to replace
                int repCountB = -1; // Number of pages from docB to insert

                if ("SLAPP".equals(formCode)) {
                    repStartA = SLAPP_REP_START_A;
                    repEndA = SLAPP_REP_END_A;
                    repCountB = SLAPP_REP_COUNT_B;
                } else if ("SLGII".equals(formCode)) {
                    repStartA = SLGII_REP_START_A;
                    repEndA = SLGII_REP_END_A;
                    repCountB = SLGII_REP_COUNT_B;
                }

                if (repStartA != -1 && totalPagesA >= repEndA) {
                    // This block handles all multi-page replacements
                    
                    // A. Copy pages 1 up to (repStartA - 1)
                    if (repStartA > 1) {
                        merger.merge(docA, 1, repStartA - 1);
                    }

                    // B. Insert replacement pages from PDF B (if available)
                    if (pdfBBytes != null && pdfBBytes.length > 0) {
                        try (PdfReader readerB = new PdfReader(new ByteArrayInputStream(pdfBBytes));
                            PdfDocument docB = new PdfDocument(readerB)) {
                            
                            // Copy the required number of pages from docB starting from page 1
                            if (docB.getNumberOfPages() >= repCountB) {
                                merger.merge(docB, 1, repCountB);
                            } else {
                                // Log or handle case where pdfB is too short
                                System.err.println("PDF B too short for " + formCode + " replacement.");
                            }
                        }
                    }

                    // C. Copy pages (repEndA + 1) through the end
                    if (totalPagesA > repEndA) {
                        merger.merge(docA, repEndA + 1, totalPagesA);
                    }
                
                // --- Single Page Replacement Forms (New/Existing Logic) ---
                } else if ("MLB03S".equals(formCode) && totalPagesA >= MLB03S_REP_PAGE_A) {
                    // MLB03S: REPLACE page 12 with PDF B page 1 (New Requirement)
                    
                    // A. Copy pages 1 up to 11 (MLB03S_REP_PAGE_A - 1)
                    if (MLB03S_REP_PAGE_A > 1) {
                        merger.merge(docA, 1, MLB03S_REP_PAGE_A - 1);
                    }
                    
                    // B. Insert replacement page from PDF B (if available)
                    if (pdfBBytes != null && pdfBBytes.length > 0) {
                        try (PdfReader readerB = new PdfReader(new ByteArrayInputStream(pdfBBytes));
                            PdfDocument docB = new PdfDocument(readerB)) {
                            
                            // Copy ONLY page 1 from docB
                            if (docB.getNumberOfPages() >= 1) {
                                merger.merge(docB, 1, 1);
                            }
                        }
                    }
                    
                    // C. Copy pages 13 through the end (MLB03S_REP_PAGE_A + 1)
                    if (totalPagesA > MLB03S_REP_PAGE_A) {
                        merger.merge(docA, MLB03S_REP_PAGE_A + 1, totalPagesA);
                    }

                } else {
                    // Default: Copy all pages from docA
                    merger.merge(docA, 1, totalPagesA);
                }
            } 
            
            // 3. Close the merged PDF document
            mergedPdf.close(); 
            
            // 4. Return the resulting byte array
            return baos.toByteArray();

        } // baos is closed here
    }
}