"""
Report template configuration for qry-doc.

This module provides the ReportTemplate class for customizing
the appearance of generated PDF reports.
"""
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any, Optional, Callable

from reportlab.lib.pagesizes import letter, A4
from reportlab.lib.colors import HexColor, Color
from reportlab.lib.units import inch


# Type alias for page size tuples
PageSize = tuple[float, float]


@dataclass
class ReportTemplate:
    """
    Configuration for PDF report styling.
    
    Attributes:
        logo_path: Path to logo image file (PNG, JPG, or SVG).
        primary_color: Hex color for headings and accents (e.g., "#1a1a2e").
        title_font: Font family for titles (e.g., "Helvetica-Bold").
        body_font: Font family for body text (e.g., "Helvetica").
        page_size: Page dimensions as (width, height) tuple.
        margin_top: Top margin in points.
        margin_bottom: Bottom margin in points.
        margin_left: Left margin in points.
        margin_right: Right margin in points.
        header_height: Height reserved for header in points.
        footer_height: Height reserved for footer in points.
    """
    
    logo_path: Optional[Path] = None
    primary_color: str = "#1a1a2e"
    title_font: str = "Helvetica-Bold"
    body_font: str = "Helvetica"
    page_size: PageSize = field(default_factory=lambda: letter)
    margin_top: float = 72.0  # 1 inch
    margin_bottom: float = 72.0
    margin_left: float = 72.0
    margin_right: float = 72.0
    header_height: float = 50.0
    footer_height: float = 30.0
    
    # Callbacks for custom header/footer (set after initialization)
    _header_callback: Optional[Callable[[Any, Any], None]] = field(
        default=None, repr=False
    )
    _footer_callback: Optional[Callable[[Any, Any], None]] = field(
        default=None, repr=False
    )
    
    def __post_init__(self) -> None:
        """Validate and convert fields after initialization."""
        # Convert string path to Path object
        if isinstance(self.logo_path, str):
            self.logo_path = Path(self.logo_path)
        
        # Validate color format
        if not self.primary_color.startswith("#"):
            self.primary_color = f"#{self.primary_color}"
    
    @property
    def primary_color_obj(self) -> Color:
        """Get the primary color as a ReportLab Color object."""
        return HexColor(self.primary_color)
    
    @property
    def page_width(self) -> float:
        """Get the page width in points."""
        return self.page_size[0]
    
    @property
    def page_height(self) -> float:
        """Get the page height in points."""
        return self.page_size[1]
    
    @property
    def content_width(self) -> float:
        """Get the available content width (page width minus margins)."""
        return self.page_width - self.margin_left - self.margin_right
    
    @property
    def content_height(self) -> float:
        """Get the available content height (page height minus margins and header/footer)."""
        return (
            self.page_height 
            - self.margin_top 
            - self.margin_bottom 
            - self.header_height 
            - self.footer_height
        )
    
    def draw_header(self, canvas: Any, doc: Any) -> None:
        """
        Draw the header on the current page.
        
        Override this method or set _header_callback for custom headers.
        
        Args:
            canvas: ReportLab canvas object.
            doc: ReportLab document object.
        """
        if self._header_callback is not None:
            self._header_callback(canvas, doc)
            return
        
        # Default header implementation
        canvas.saveState()
        
        # Draw logo if provided
        if self.logo_path and self.logo_path.exists():
            try:
                canvas.drawImage(
                    str(self.logo_path),
                    self.margin_left,
                    self.page_height - self.margin_top - 40,
                    width=100,
                    height=40,
                    preserveAspectRatio=True,
                    mask='auto'
                )
            except Exception:
                pass  # Skip logo if it can't be loaded
        
        # Draw a line under the header
        canvas.setStrokeColor(self.primary_color_obj)
        canvas.setLineWidth(1)
        y_pos = self.page_height - self.margin_top - self.header_height
        canvas.line(
            self.margin_left,
            y_pos,
            self.page_width - self.margin_right,
            y_pos
        )
        
        canvas.restoreState()
    
    def draw_footer(self, canvas: Any, doc: Any) -> None:
        """
        Draw the footer on the current page.
        
        Override this method or set _footer_callback for custom footers.
        
        Args:
            canvas: ReportLab canvas object.
            doc: ReportLab document object.
        """
        if self._footer_callback is not None:
            self._footer_callback(canvas, doc)
            return
        
        # Default footer implementation
        canvas.saveState()
        
        # Draw page number
        page_num = doc.page
        canvas.setFont(self.body_font, 9)
        canvas.setFillColor(HexColor("#666666"))
        
        text = f"Página {page_num}"
        canvas.drawCentredString(
            self.page_width / 2,
            self.margin_bottom - 20,
            text
        )
        
        # Draw a line above the footer
        canvas.setStrokeColor(HexColor("#cccccc"))
        canvas.setLineWidth(0.5)
        y_pos = self.margin_bottom
        canvas.line(
            self.margin_left,
            y_pos,
            self.page_width - self.margin_right,
            y_pos
        )
        
        canvas.restoreState()
    
    def set_header_callback(self, callback: Callable[[Any, Any], None]) -> None:
        """
        Set a custom header drawing callback.
        
        Args:
            callback: Function that takes (canvas, doc) and draws the header.
        """
        self._header_callback = callback
    
    def set_footer_callback(self, callback: Callable[[Any, Any], None]) -> None:
        """
        Set a custom footer drawing callback.
        
        Args:
            callback: Function that takes (canvas, doc) and draws the footer.
        """
        self._footer_callback = callback


# Pre-defined templates
DEFAULT_TEMPLATE = ReportTemplate()

CORPORATE_TEMPLATE = ReportTemplate(
    primary_color="#003366",
    title_font="Helvetica-Bold",
    body_font="Helvetica",
    page_size=letter,
)

MINIMAL_TEMPLATE = ReportTemplate(
    primary_color="#333333",
    title_font="Helvetica",
    body_font="Helvetica",
    header_height=20.0,
    footer_height=20.0,
)

A4_TEMPLATE = ReportTemplate(
    page_size=A4,
)
