"""
Tests for web/services/pdf_service.py

Tests cover:
- PDFService initialization
- Markdown to HTML conversion
- Markdown to PDF conversion
- Error handling
- Singleton pattern
"""

import pytest
from unittest.mock import patch


class TestPDFServiceInit:
    """Tests for PDFService initialization."""

    def test_pdf_service_init(self):
        """Test PDFService initializes with minimal CSS."""
        from local_deep_research.web.services.pdf_service import PDFService

        service = PDFService()

        assert service.minimal_css is not None

    def test_pdf_service_css_contains_a4(self):
        """Test that CSS sets A4 page size."""
        from local_deep_research.web.services.pdf_service import PDFService

        service = PDFService()

        # The CSS string should be accessible
        assert service.minimal_css is not None


class TestMarkdownToHTML:
    """Tests for _markdown_to_html method."""

    def test_markdown_to_html_basic(self):
        """Test basic markdown conversion."""
        from local_deep_research.web.services.pdf_service import PDFService

        service = PDFService()
        markdown = "# Hello World\n\nThis is a **test**."

        html = service._markdown_to_html(markdown)

        # h1 may have an id attribute added by markdown TOC extension
        assert "Hello World</h1>" in html
        assert "<strong>test</strong>" in html
        assert "<!DOCTYPE html>" in html
        assert "</html>" in html

    def test_markdown_to_html_with_title(self):
        """Test conversion with title."""
        from local_deep_research.web.services.pdf_service import PDFService

        service = PDFService()
        markdown = "Content here"

        html = service._markdown_to_html(markdown, title="Test Title")

        assert "<title>Test Title</title>" in html

    def test_markdown_to_html_escapes_html_in_title(self):
        """Test that HTML special characters in title are escaped."""
        from local_deep_research.web.services.pdf_service import PDFService

        service = PDFService()

        html = service._markdown_to_html(
            "content", title='<script>alert("xss")</script>'
        )

        assert "<script>" not in html
        assert "&lt;script&gt;" in html

    def test_markdown_to_html_escapes_html_in_metadata(self):
        """Test that HTML special characters in metadata are escaped."""
        from local_deep_research.web.services.pdf_service import PDFService

        service = PDFService()
        metadata = {"<b>key</b>": '<img src="x" onerror="alert(1)">'}

        html = service._markdown_to_html("content", metadata=metadata)

        assert "<b>key</b>" not in html
        assert "&lt;b&gt;key&lt;/b&gt;" in html
        assert 'onerror="alert(1)"' not in html

    def test_markdown_to_html_with_metadata(self):
        """Test conversion with metadata."""
        from local_deep_research.web.services.pdf_service import PDFService

        service = PDFService()
        markdown = "Content"
        metadata = {"author": "Test Author", "date": "2024-01-01"}

        html = service._markdown_to_html(markdown, metadata=metadata)

        assert 'name="author"' in html
        assert 'content="Test Author"' in html
        assert 'name="date"' in html

    def test_markdown_to_html_tables(self):
        """Test table markdown is converted."""
        from local_deep_research.web.services.pdf_service import PDFService

        service = PDFService()
        markdown = """
| Header 1 | Header 2 |
|----------|----------|
| Cell 1   | Cell 2   |
"""
        html = service._markdown_to_html(markdown)

        assert "<table>" in html
        assert "<th>" in html or "<td>" in html

    def test_markdown_to_html_code_blocks(self):
        """Test fenced code blocks are converted."""
        from local_deep_research.web.services.pdf_service import PDFService

        service = PDFService()
        markdown = """
```python
def hello():
    print("Hello")
```
"""
        html = service._markdown_to_html(markdown)

        assert "<pre>" in html or "<code>" in html

    def test_markdown_to_html_includes_footer(self):
        """Test that footer with LDR attribution is included."""
        from local_deep_research.web.services.pdf_service import PDFService

        service = PDFService()
        markdown = "Test content"

        html = service._markdown_to_html(markdown)

        assert "Local Deep Research" in html or "LDR" in html


class TestMarkdownToPDF:
    """Tests for markdown_to_pdf method."""

    def test_markdown_to_pdf_returns_bytes(self):
        """Test that PDF conversion returns bytes."""
        from local_deep_research.web.services.pdf_service import PDFService

        service = PDFService()
        markdown = "# Test Document\n\nThis is a test."

        pdf_bytes = service.markdown_to_pdf(markdown)

        assert isinstance(pdf_bytes, bytes)
        assert len(pdf_bytes) > 0
        # PDF files start with %PDF
        assert pdf_bytes[:4] == b"%PDF"

    def test_markdown_to_pdf_with_title(self):
        """Test PDF conversion with title."""
        from local_deep_research.web.services.pdf_service import PDFService

        service = PDFService()
        markdown = "Content here"

        pdf_bytes = service.markdown_to_pdf(markdown, title="My Document")

        assert isinstance(pdf_bytes, bytes)
        assert len(pdf_bytes) > 0

    def test_markdown_to_pdf_with_metadata(self):
        """Test PDF conversion with metadata."""
        from local_deep_research.web.services.pdf_service import PDFService

        service = PDFService()
        markdown = "Content"
        metadata = {"author": "Test Author"}

        pdf_bytes = service.markdown_to_pdf(markdown, metadata=metadata)

        assert isinstance(pdf_bytes, bytes)

    def test_markdown_to_pdf_with_custom_css(self):
        """Test PDF conversion with custom CSS."""
        from local_deep_research.web.services.pdf_service import PDFService

        service = PDFService()
        markdown = "# Styled Content"
        custom_css = "body { color: red; }"

        pdf_bytes = service.markdown_to_pdf(markdown, custom_css=custom_css)

        assert isinstance(pdf_bytes, bytes)
        assert len(pdf_bytes) > 0

    def test_markdown_to_pdf_complex_document(self):
        """Test PDF conversion with complex document."""
        from local_deep_research.web.services.pdf_service import PDFService

        service = PDFService()
        markdown = """
# Research Report

## Introduction

This is a comprehensive research document.

### Key Findings

1. First finding
2. Second finding
3. Third finding

### Data Table

| Metric | Value |
|--------|-------|
| A      | 100   |
| B      | 200   |

## Conclusion

The research concludes that **testing is important**.

```python
def analyze():
    return True
```
"""
        pdf_bytes = service.markdown_to_pdf(
            markdown,
            title="Research Report",
            metadata={"author": "Research Team", "date": "2024"},
        )

        assert isinstance(pdf_bytes, bytes)
        assert len(pdf_bytes) > 100  # Should be a reasonable size

    def test_markdown_to_pdf_empty_content(self):
        """Test PDF conversion with empty content."""
        from local_deep_research.web.services.pdf_service import PDFService

        service = PDFService()
        markdown = ""

        pdf_bytes = service.markdown_to_pdf(markdown)

        # Should still generate valid PDF
        assert isinstance(pdf_bytes, bytes)
        assert pdf_bytes[:4] == b"%PDF"


class TestGetPDFService:
    """Tests for get_pdf_service singleton function."""

    def test_get_pdf_service_returns_instance(self):
        """Test that get_pdf_service returns a PDFService instance."""
        # Reset singleton for test
        import local_deep_research.web.services.pdf_service as pdf_module

        pdf_module._pdf_service = None

        from local_deep_research.web.services.pdf_service import get_pdf_service

        service = get_pdf_service()

        assert service is not None
        from local_deep_research.web.services.pdf_service import PDFService

        assert isinstance(service, PDFService)

    def test_get_pdf_service_singleton(self):
        """Test that get_pdf_service returns same instance."""
        # Reset singleton for test
        import local_deep_research.web.services.pdf_service as pdf_module

        pdf_module._pdf_service = None

        from local_deep_research.web.services.pdf_service import get_pdf_service

        service1 = get_pdf_service()
        service2 = get_pdf_service()

        assert service1 is service2


class TestPDFServiceErrorHandling:
    """Tests for error handling in PDF service."""

    def test_markdown_to_pdf_raises_on_error(self):
        """Test that exceptions are propagated."""
        from local_deep_research.web.services.pdf_service import PDFService

        service = PDFService()

        # Mock HTML to raise an exception
        with patch(
            "local_deep_research.web.services.pdf_service.HTML"
        ) as mock_html:
            mock_html.side_effect = Exception("Conversion error")

            with pytest.raises(Exception) as exc_info:
                service.markdown_to_pdf("test")

            assert "Conversion error" in str(exc_info.value)
