"""
Authorization Detail PDF Generator.

Renders a full authorization detail PDF using WeasyPrint + Jinja2.
The template (authorization_detail.html) lives in src/apps/invoices/templates/
alongside the invoice and auth-certificate templates.
"""

import logging
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Dict, List, Optional

import jinja2

logger = logging.getLogger(__name__)

# Point at the shared invoice templates directory
TEMPLATES_DIR = Path(__file__).parent.parent.parent / "invoices" / "templates"


def _fmt_dt(dt: Optional[Any]) -> str:
    """Format a datetime (or ISO string) to a human-readable string."""
    if dt is None:
        return "—"
    if isinstance(dt, str):
        try:
            dt = datetime.fromisoformat(dt)
        except (ValueError, TypeError):
            return str(dt)
    if isinstance(dt, datetime):
        # Strip microseconds for cleaner output
        if dt.tzinfo is not None:
            dt = dt.astimezone(timezone.utc).replace(tzinfo=None)
        return dt.strftime("%b %d, %Y  %H:%M UTC")
    return str(dt)


def _customer_display_name(customer: Optional[Any]) -> str:
    if customer is None:
        return "N/A"
    parts = [
        getattr(customer, "first_name", None) or "",
        getattr(customer, "last_name", None) or "",
    ]
    name = " ".join(p for p in parts if p).strip()
    if name:
        return name
    return getattr(customer, "business_legal_name", None) or "N/A"


def _payer_display_name(payer: Optional[Any]) -> str:
    if payer is None:
        return "N/A"
    parts = [
        getattr(payer, "first_name", None) or "",
        getattr(payer, "last_name", None) or "",
    ]
    name = " ".join(p for p in parts if p).strip()
    return name or "N/A"


class AuthDetailPDFGenerator:
    """Render a full authorization detail PDF for the given authorization."""

    def __init__(self) -> None:
        self._env = jinja2.Environment(
            loader=jinja2.FileSystemLoader(str(TEMPLATES_DIR)),
            autoescape=True,
        )

    def generate_pdf(
        self,
        *,
        auth: Any,
        merchant: Any,
        proof: Optional[Any] = None,
        history: Optional[List[Any]] = None,
        invoices: Optional[List[Any]] = None,
        transactions: Optional[List[Any]] = None,
    ) -> bytes:
        """
        Render authorization_detail.html and return PDF bytes.

        Args:
            auth:         AuthorizationDetailResponse (or ORM record with same fields)
            merchant:     Merchant ORM record (must have .name, .email, .id)
            proof:        AuthorizationProofSchema or None
            history:      List[AuthorizationHistoryEvent] or None
            invoices:     List[AssociatedInvoiceSchema] or None
            transactions: List[AssociatedTransactionSchema] or None

        Raises:
            ImportError:  WeasyPrint not installed
            RuntimeError: Rendering failure
        """
        try:
            import weasyprint  # noqa: F401 lazy import
        except ImportError as exc:
            raise ImportError(
                "WeasyPrint is required for PDF generation. "
                "Install with: pip install weasyprint"
            ) from exc

        auth_literal = (
            getattr(auth, "authorization_literal", None)
            or f"AUTH-{getattr(auth, 'id', '')}"
        )
        merchant_name = getattr(merchant, "name", None) or "Merchant"
        merchant_email = getattr(merchant, "email", None) or ""
        generated_at = datetime.utcnow().strftime("%b %d, %Y  %H:%M UTC")

        # Format history event dates for display
        formatted_history: List[Dict[str, str]] = []
        for evt in (history or []):
            formatted_history.append(
                {
                    "event": getattr(evt, "event", str(evt)),
                    "occurred_at": _fmt_dt(getattr(evt, "occurred_at", None)),
                }
            )

        # Format invoice dates for display
        formatted_invoices: List[Dict[str, Any]] = []
        for inv in (invoices or []):
            formatted_invoices.append(
                {
                    "invoice_literal": getattr(inv, "invoice_literal", None)
                                       or getattr(inv, "invoice_id", None),
                    "amount": getattr(inv, "amount", None),
                    "status": getattr(inv, "status", None),
                    "status_text": getattr(inv, "status_text", None),
                    "created_at": _fmt_dt(getattr(inv, "created_at", None)),
                    "due_date": _fmt_dt(getattr(inv, "due_date", None)),
                }
            )

        # Format transaction dates for display
        formatted_transactions: List[Dict[str, Any]] = []
        for txn in (transactions or []):
            formatted_transactions.append(
                {
                    "txn_literal": getattr(txn, "txn_literal", None)
                                   or getattr(txn, "txn_id", None),
                    "txn_amount": getattr(txn, "txn_amount", None),
                    "txn_status": getattr(txn, "txn_status", None),
                    "status_text": getattr(txn, "status_text", None),
                    "payment_type": getattr(txn, "payment_type", None),
                    "ocurred_at": _fmt_dt(getattr(txn, "ocurred_at", None)),
                }
            )

        template = self._env.get_template("authorization_detail.html")
        html_content = template.render(
            auth_literal=auth_literal,
            merchant_name=merchant_name,
            merchant_email=merchant_email,
            generated_at=generated_at,
            # Core auth fields
            status=getattr(auth, "status", None),
            authorization_type=getattr(auth, "authorization_type", None),
            authorization_date=_fmt_dt(getattr(auth, "authorization_date", None)),
            is_verified=getattr(auth, "is_verified", False),
            created_at=_fmt_dt(getattr(auth, "created_at", None)),
            expired_at=_fmt_dt(getattr(auth, "expired_at", None)),
            # Nested
            customer=getattr(auth, "customer", None),
            customer_display_name=_customer_display_name(
                getattr(auth, "customer", None)
            ),
            payer=getattr(auth, "payer", None),
            payer_display_name=_payer_display_name(getattr(auth, "payer", None)),
            payment_request=getattr(auth, "payment_request", None),
            hpp_session=getattr(auth, "hpp_session", None),
            # Proof / history / associations
            proof=proof,
            history=formatted_history,
            invoices=formatted_invoices,
            transactions=formatted_transactions,
        )

        try:
            return weasyprint.HTML(string=html_content).write_pdf()
        except Exception as exc:
            logger.error(
                "Authorization detail PDF generation failed: %s", exc, exc_info=True
            )
            raise RuntimeError(
                f"Authorization detail PDF generation failed: {exc}"
            ) from exc
