"""Tests for PDF exporter."""

from __future__ import annotations

import pytest

from noteflow.domain.entities import ActionItem, KeyPoint, Meeting, Segment, Summary


def _check_weasyprint_available() -> bool:
    """Check if weasyprint is available with working native libraries."""
    try:
        from weasyprint import HTML

        # Reference the import to satisfy type checker
        del HTML
        return True
    except (ImportError, OSError):
        # ImportError: weasyprint not installed
        # OSError: weasyprint installed but native libs (GTK/GLib) missing
        return False


WEASYPRINT_AVAILABLE = _check_weasyprint_available()


pytestmark = pytest.mark.skipif(
    not WEASYPRINT_AVAILABLE,
    reason="weasyprint not available - requires GTK/GLib native libraries",
)


class TestPdfExporter:
    """Tests for PdfExporter output."""

    def test_export_returns_bytes(self) -> None:
        """PDF export returns bytes, not string."""
        from noteflow.infrastructure.export.pdf import PdfExporter

        meeting = Meeting.create(title="Test Meeting")
        segments = [
            Segment(segment_id=0, text="Hello world", start_time=0.0, end_time=1.0),
        ]

        exporter = PdfExporter()
        result = exporter.export(meeting, segments)

        assert isinstance(result, bytes), "PDF export should return bytes"
        assert len(result) > 0, "PDF export should produce non-empty content"

    def test_export_is_valid_pdf(self) -> None:
        """PDF export produces valid PDF file starting with magic bytes."""
        from noteflow.infrastructure.export.pdf import PdfExporter

        meeting = Meeting.create(title="Test Meeting")
        segments = [
            Segment(segment_id=0, text="Hello world", start_time=0.0, end_time=1.0),
        ]

        exporter = PdfExporter()
        result = exporter.export(meeting, segments)

        assert result.startswith(b"%PDF-"), "PDF should start with %PDF- magic bytes"

    def test_export_includes_title(self) -> None:
        """PDF HTML content contains meeting title."""
        from noteflow.infrastructure.export.pdf import PdfExporter

        meeting = Meeting.create(title="Important Meeting")
        segments = [
            Segment(segment_id=0, text="Hello", start_time=0.0, end_time=1.0),
        ]

        exporter = PdfExporter()
        html_content = exporter.build_html(meeting, segments)

        assert "Important Meeting" in html_content, "HTML should contain meeting title"

    def test_export_includes_segments(self) -> None:
        """PDF HTML content contains all segments with speakers."""
        from noteflow.infrastructure.export.pdf import PdfExporter

        meeting = Meeting.create(title="Test")
        segments = [
            Segment(
                segment_id=0,
                text="Hello, welcome to the meeting.",
                start_time=0.0,
                end_time=5.0,
                speaker_id="Alice",
            ),
            Segment(
                segment_id=1,
                text="Thank you for joining.",
                start_time=5.0,
                end_time=10.0,
                speaker_id="Bob",
            ),
        ]

        exporter = PdfExporter()
        html_content = exporter.build_html(meeting, segments)

        assert "Hello, welcome to the meeting." in html_content, "first segment text"
        assert "Thank you for joining." in html_content, "second segment text"
        assert "Alice" in html_content, "first speaker"
        assert "Bob" in html_content, "second speaker"

    def test_export_includes_summary(self) -> None:
        """PDF HTML content contains summary when present."""
        from noteflow.infrastructure.export.pdf import PdfExporter

        meeting = Meeting.create(title="Test")
        meeting.summary = Summary(
            meeting_id=meeting.id,
            executive_summary="This was a productive meeting.",
            key_points=[KeyPoint(text="Discussed project timeline")],
            action_items=[ActionItem(text="Follow up with client", assignee="Alice")],
        )
        segments = [
            Segment(segment_id=0, text="Hello", start_time=0.0, end_time=1.0),
        ]

        exporter = PdfExporter()
        html_content = exporter.build_html(meeting, segments)

        assert "productive meeting" in html_content, "HTML should contain executive summary"
        assert "project timeline" in html_content, "HTML should contain key points"
        assert "Follow up with client" in html_content, "HTML should contain action items"

    def test_export_escapes_html_characters(self) -> None:
        """PDF properly escapes HTML special characters to prevent injection."""
        from noteflow.infrastructure.export.pdf import PdfExporter

        meeting = Meeting.create(title="<script>alert('xss')</script>")
        segments = [
            Segment(
                segment_id=0,
                text="Hello <b>world</b> & friends",
                start_time=0.0,
                end_time=1.0,
                speaker_id="Bob<script>",
            ),
        ]

        exporter = PdfExporter()
        html_content = exporter.build_html(meeting, segments)

        assert "<script>" not in html_content, "raw script tag must be escaped"
        assert "&lt;script&gt;" in html_content, "script tag should be HTML-escaped"
        assert "<b>" not in html_content, "raw bold tag must be escaped"
        assert "&lt;b&gt;" in html_content, "bold tag should be HTML-escaped"
        assert "&amp;" in html_content, "ampersand should be HTML-escaped"

    def test_export_handles_empty_segments(self) -> None:
        """PDF export handles meeting with no segments."""
        from noteflow.infrastructure.export.pdf import PdfExporter

        meeting = Meeting.create(title="Empty Meeting")
        segments: list[Segment] = []

        exporter = PdfExporter()
        result = exporter.export(meeting, segments)

        assert isinstance(result, bytes), "empty meeting PDF should return bytes"
        assert result.startswith(b"%PDF-"), "empty meeting PDF should have valid magic bytes"

    def test_format_properties(self) -> None:
        """PDF exporter has correct format name and extension."""
        from noteflow.infrastructure.export.pdf import PdfExporter

        exporter = PdfExporter()

        assert exporter.format_name == "PDF", "format_name should be 'PDF'"
        assert exporter.file_extension == ".pdf", "file_extension should be '.pdf'"


class TestPdfExporterNotInstalled:
    """Tests for PdfExporter when weasyprint is not available."""

    def test_raises_runtime_error_when_weasyprint_missing(
        self, monkeypatch: pytest.MonkeyPatch
    ) -> None:
        """Raise RuntimeError with install instructions when weasyprint unavailable."""
        import noteflow.infrastructure.export.pdf as pdf_module

        # Mock _get_weasy_html to return None (simulating missing weasyprint)
        monkeypatch.setattr(pdf_module, "_get_weasy_html", lambda: None)

        from noteflow.infrastructure.export.pdf import PdfExporter

        meeting = Meeting.create(title="Test")
        segments = [
            Segment(segment_id=0, text="Hello", start_time=0.0, end_time=1.0),
        ]

        exporter = PdfExporter()

        with pytest.raises(RuntimeError, match="weasyprint is not installed"):
            exporter.export(meeting, segments)
