"""
PDF Export Module for Scientific Gallery Generator

This module handles exporting and merging multiple plots into a single PDF
using PyPDF2 and reportlab for layout.
"""

import io
import tempfile
from pathlib import Path
from typing import List, Dict, Any
import subprocess

try:
    from PyPDF2 import PdfReader, PdfWriter
    from reportlab.pdfgen import canvas
    from reportlab.lib.pagesizes import letter, A4
    from reportlab.lib.utils import ImageReader
    HAS_PDF_LIBS = True
except ImportError:
    HAS_PDF_LIBS = False


class PDFExporter:
    """Handles exporting multiple plots to a merged PDF"""
    
    def __init__(self):
        self.page_size = A4
        self.margin = 50
        
    def merge_plots(self, plot_paths: List[str], layout: Dict[str, int], 
                   output_path: str = None) -> bytes:
        """
        Merge multiple PDF plots into a single PDF with grid layout.
        
        Args:
            plot_paths: List of paths to PDF files
            layout: Dictionary with 'rows' and 'cols' keys
            output_path: Optional output file path
            
        Returns:
            PDF bytes
        """
        if not HAS_PDF_LIBS:
            return self._merge_with_pdfjam(plot_paths, layout, output_path)
        
        return self._merge_with_pypdf(plot_paths, layout, output_path)
    
    def _merge_with_pypdf(self, plot_paths: List[str], layout: Dict[str, int], 
                         output_path: str = None) -> bytes:
        """Merge PDFs using PyPDF2 and reportlab"""
        from reportlab.pdfgen import canvas
        from reportlab.lib.pagesizes import A4
        
        # Create a new PDF with the layout
        buffer = io.BytesIO()
        c = canvas.Canvas(buffer, pagesize=A4)
        page_width, page_height = A4
        
        rows = layout['rows']
        cols = layout['cols']
        
        # Calculate dimensions for each plot
        plot_width = (page_width - 2 * self.margin) / cols
        plot_height = (page_height - 2 * self.margin) / rows
        
        # Place each plot in the grid
        for i, plot_path in enumerate(plot_paths):
            if i >= rows * cols:
                break
                
            row = i // cols
            col = i % cols
            
            # Calculate position
            x = self.margin + col * plot_width
            y = page_height - self.margin - (row + 1) * plot_height
            
            try:
                # Read the source PDF
                with open(plot_path, 'rb') as f:
                    reader = PdfReader(f)
                    if len(reader.pages) > 0:
                        page = reader.pages[0]
                        
                        # Convert PDF page to image and place it
                        # This is a simplified approach - in practice you'd want
                        # to properly scale and position the PDF content
                        self._draw_pdf_placeholder(c, x, y, plot_width, plot_height, 
                                                 Path(plot_path).stem)
                        
            except Exception as e:
                print(f"Error processing {plot_path}: {e}")
                self._draw_error_placeholder(c, x, y, plot_width, plot_height)
        
        c.save()
        
        if output_path:
            with open(output_path, 'wb') as f:
                f.write(buffer.getvalue())
        
        return buffer.getvalue()
    
    def _merge_with_pdfjam(self, plot_paths: List[str], layout: Dict[str, int], 
                          output_path: str = None) -> bytes:
        """Merge PDFs using pdfjam (requires pdfpages LaTeX package)"""
        rows = layout['rows']
        cols = layout['cols']
        
        # Create temporary output file
        with tempfile.NamedTemporaryFile(suffix='.pdf', delete=False) as tmp_file:
            temp_output = tmp_file.name
        
        try:
            # Build pdfjam command
            cmd = [
                'pdfjam',
                '--nup', f'{cols}x{rows}',
                '--landscape' if cols > rows else '--no-landscape',
                '--frame', 'true',
                '--delta', '10pt 10pt',
                '--offset', '0pt 0pt',
                '--outfile', temp_output
            ]
            
            # Add input files
            cmd.extend(plot_paths[:rows * cols])
            
            # Run pdfjam
            result = subprocess.run(cmd, capture_output=True, text=True)
            
            if result.returncode != 0:
                raise Exception(f"pdfjam failed: {result.stderr}")
            
            # Read the output file
            with open(temp_output, 'rb') as f:
                pdf_bytes = f.read()
            
            if output_path:
                with open(output_path, 'wb') as f:
                    f.write(pdf_bytes)
            
            return pdf_bytes
            
        finally:
            # Clean up temporary file
            Path(temp_output).unlink(missing_ok=True)
    
    def _draw_pdf_placeholder(self, canvas, x: float, y: float, width: float, 
                             height: float, plot_name: str):
        """Draw a placeholder for a PDF plot"""
        # Draw border
        canvas.setStrokeColorRGB(0.5, 0.5, 0.5)
        canvas.setLineWidth(1)
        canvas.rect(x, y, width, height)
        
        # Draw plot name
        canvas.setFillColorRGB(0, 0, 0)
        canvas.setFont("Helvetica", 10)
        text_width = canvas.stringWidth(plot_name, "Helvetica", 10)
        text_x = x + (width - text_width) / 2
        text_y = y + height / 2
        canvas.drawString(text_x, text_y, plot_name)
    
    def _draw_error_placeholder(self, canvas, x: float, y: float, width: float, 
                               height: float):
        """Draw an error placeholder"""
        # Draw red border
        canvas.setStrokeColorRGB(1, 0, 0)
        canvas.setLineWidth(2)
        canvas.rect(x, y, width, height)
        
        # Draw error text
        canvas.setFillColorRGB(1, 0, 0)
        canvas.setFont("Helvetica-Bold", 12)
        error_text = "Error loading plot"
        text_width = canvas.stringWidth(error_text, "Helvetica-Bold", 12)
        text_x = x + (width - text_width) / 2
        text_y = y + height / 2
        canvas.drawString(text_x, text_y, error_text)


def check_dependencies() -> Dict[str, bool]:
    """Check if required dependencies are available"""
    deps = {
        'pypdf2': HAS_PDF_LIBS,
        'pdfjam': False
    }
    
    # Check for pdfjam
    try:
        result = subprocess.run(['pdfjam', '--version'], 
                              capture_output=True, text=True)
        deps['pdfjam'] = result.returncode == 0
    except FileNotFoundError:
        pass
    
    return deps


if __name__ == "__main__":
    # Test the exporter
    exporter = PDFExporter()
    deps = check_dependencies()
    print("Available dependencies:", deps)
