import fitz  # PyMuPDF
import gc

def overlay_pdfs(base_pdf_path, pdf_data, output_pdf_path):
    # 'with' handles the base PDF file handle
    with fitz.open(base_pdf_path) as base_pdf:

        for i, pdf_info in enumerate(pdf_data):
            page_num = pdf_info['page'] - 1

            # 1. Read the file into a memory buffer
            # 2. Open the PDF FROM that buffer
            # Using 'with' here is CRITICAL to release the memory buffer
            # after the page is placed.
            with open(pdf_info['pdf_path'], "rb") as f:
                chart_buffer = f.read()

            with fitz.open(stream=chart_buffer, filetype="pdf") as overlay_pdf:
                base_page = base_pdf[page_num]

                position = fitz.Rect(
                    pdf_info['x'],
                    pdf_info['y'],
                    pdf_info['x'] + pdf_info['width'],
                    pdf_info['y'] + pdf_info['height']
                )

                # Place the overlay PDF
                base_page.show_pdf_page(position, overlay_pdf, 0)

            # --- GARBAGE COLLECTION ---
            # Every 100 charts, we force a deep clean
            if (i + 1) % 100 == 0:
                # Explicitly delete the buffer variable to help GC
                del chart_buffer

                # Shrink the MuPDF internal caches (images/fonts)
                fitz.TOOLS.store_shrink(100)

                # Force Python to collect unreachable memory cycles
                gc.collect()

        base_pdf.save(output_pdf_path, garbage=1, deflate=True)

    print(f"Overlay PDF saved: {output_pdf_path}")