"""PDF exporter implementation using weasyprint.

Export meeting transcripts to PDF format.
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Protocol, cast

from noteflow.config.constants import EXPORT_EXT_PDF
from noteflow.infrastructure.export._formatting import (
    escape_html,
    format_datetime,
    format_timestamp,
)

if TYPE_CHECKING:
    from collections.abc import Sequence

    from noteflow.domain.entities.meeting import Meeting
    from noteflow.domain.entities.segment import Segment


class _WeasyHTMLProtocol(Protocol):
    """Protocol for weasyprint HTML class."""

    def __init__(self, string: str) -> None: ...
    def write_pdf(self) -> bytes: ...


def _get_weasy_html() -> type[_WeasyHTMLProtocol] | None:
    """Get weasyprint HTML class if available.

    Returns:
        The weasyprint HTML class, or None if not installed.
    """
    import importlib.util

    if importlib.util.find_spec("weasyprint") is None:
        return None

    weasyprint = importlib.import_module("weasyprint")
    html_class = getattr(weasyprint, "HTML", None)
    if html_class is None:
        return None
    return cast(type[_WeasyHTMLProtocol], html_class)


# PDF-optimized CSS with A4 page settings
_PDF_CSS = """
@page {
    size: A4;
    margin: 2cm;
}

body {
    font-family: 'Helvetica Neue', Arial, sans-serif;
    font-size: 11pt;
    line-height: 1.6;
    color: #333;
}

h1 {
    color: #1a1a1a;
    border-bottom: 2px solid #333;
    padding-bottom: 8px;
    margin-bottom: 16px;
}

h2 {
    color: #444;
    margin-top: 24px;
    margin-bottom: 12px;
}

h3 {
    color: #555;
    margin-top: 16px;
    margin-bottom: 8px;
}

.metadata {
    color: #666;
    font-size: 10pt;
    margin-bottom: 20px;
    padding-bottom: 10px;
    border-bottom: 1px solid #ddd;
}

.summary {
    background-color: #f8f9fa;
    padding: 16px;
    border-radius: 4px;
    margin-bottom: 24px;
    page-break-inside: avoid;
}

.summary h2 {
    color: #2563eb;
    margin-top: 0;
}

.key-points {
    margin: 12px 0;
    padding-left: 20px;
}

.key-points li {
    margin-bottom: 8px;
}

.action-item {
    background-color: #fef3c7;
    padding: 8px 12px;
    margin: 8px 0;
    border-left: 3px solid #f59e0b;
    page-break-inside: avoid;
}

.segment {
    margin: 12px 0;
    padding: 8px 0;
    border-bottom: 1px solid #eee;
    page-break-inside: avoid;
}

.speaker {
    font-weight: bold;
    color: #2563eb;
}

.timestamp {
    color: #888;
    font-size: 9pt;
    margin-left: 8px;
}

.text {
    margin-top: 4px;
}
"""


class PdfExporter:
    """Export meeting transcripts to PDF format.

    Produces PDF documents using weasyprint with A4 page layout,
    meeting metadata, transcript with speakers/timestamps, and optional summary.
    """

    @property
    def format_name(self) -> str:
        """Human-readable format name."""
        return "PDF"

    @property
    def file_extension(self) -> str:
        """File extension for PDF."""
        return EXPORT_EXT_PDF

    def export(
        self,
        meeting: Meeting,
        segments: Sequence[Segment],
    ) -> bytes:
        """Export meeting transcript to PDF bytes.

        Args:
            meeting: Meeting entity with metadata.
            segments: Ordered list of transcript segments.

        Returns:
            PDF document as bytes.

        Raises:
            RuntimeError: If weasyprint is not installed.
        """
        weasy_html = _get_weasy_html()
        if weasy_html is None:
            raise RuntimeError(
                "weasyprint is not installed. Install with: pip install noteflow[pdf]"
            )

        html_content = self.build_html(meeting, segments)
        pdf_bytes: bytes = weasy_html(string=html_content).write_pdf()
        return pdf_bytes

    def build_html(self, meeting: Meeting, segments: Sequence[Segment]) -> str:
        """Build HTML content for PDF rendering.

        This method is public to allow testing HTML generation without
        PDF conversion overhead.

        Args:
            meeting: Meeting entity with metadata.
            segments: Ordered list of transcript segments.

        Returns:
            HTML string for PDF conversion.
        """
        title = escape_html(meeting.title)
        date = format_datetime(meeting.created_at)
        duration = format_timestamp(meeting.duration_seconds)

        segments_html = self._build_segments_html(segments)
        summary_html = self._build_summary_html(meeting) if meeting.summary else ""

        return f"""<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>{title}</title>
    <style>{_PDF_CSS}</style>
</head>
<body>
    <h1>{title}</h1>
    <div class="metadata">
        <strong>Date:</strong> {escape_html(date)} |
        <strong>Duration:</strong> {duration} |
        <strong>Segments:</strong> {len(segments)}
    </div>
    {summary_html}
    <h2>Transcript</h2>
    {segments_html}
</body>
</html>"""

    def _build_segments_html(self, segments: Sequence[Segment]) -> str:
        """Build HTML for transcript segments.

        Args:
            segments: Ordered list of transcript segments.

        Returns:
            HTML string for segments.
        """
        parts: list[str] = []

        for segment in segments:
            speaker = escape_html(segment.speaker_id or "Unknown")
            timestamp = format_timestamp(segment.start_time)
            text = escape_html(segment.text)

            parts.append(f"""
<div class="segment">
    <span class="speaker">{speaker}</span>
    <span class="timestamp">[{timestamp}]</span>
    <div class="text">{text}</div>
</div>""")

        return "\n".join(parts)

    def _build_summary_html(self, meeting: Meeting) -> str:
        """Build HTML for meeting summary.

        Args:
            meeting: Meeting entity with summary.

        Returns:
            HTML string for summary section.
        """
        summary = meeting.summary
        if not summary:
            return ""

        exec_summary = escape_html(summary.executive_summary)

        key_points_html = ""
        if summary.key_points:
            items = "\n".join(
                f"<li>{escape_html(kp.text)}</li>" for kp in summary.key_points
            )
            key_points_html = f"""
<h3>Key Points</h3>
<ul class="key-points">
    {items}
</ul>"""

        action_items_html = ""
        if summary.action_items:
            items = "\n".join(
                f'<div class="action-item">{escape_html(ai.text)}</div>'
                for ai in summary.action_items
            )
            action_items_html = f"""
<h3>Action Items</h3>
{items}"""

        return f"""
<div class="summary">
    <h2>Summary</h2>
    <p>{exec_summary}</p>
    {key_points_html}
    {action_items_html}
</div>"""
