"""Functional tests for PDF extraction — uses real PyMuPDF to create + extract PDFs."""

from __future__ import annotations

from pathlib import Path

import pymupdf

from axm_bib.extract import extract_pdf
from axm_bib.models import ExtractionResult
from axm_bib.tools.bib_extract import BibExtractTool


def _create_test_pdf(path: Path, *, with_image: bool = True) -> None:
    """Create a minimal real PDF with text and optionally an embedded image.

    Args:
        path: Where to save the PDF.
        with_image: Whether to embed a PNG image.
    """
    doc = pymupdf.open()

    # Page 1: text
    page1 = doc.new_page(width=612, height=792)
    page1.insert_text((72, 100), "Title of the Paper", fontsize=20)
    page1.insert_text((72, 140), "This is the abstract of the paper.", fontsize=12)
    page1.insert_text((72, 170), "It contains important findings.", fontsize=12)

    # Page 2: text + optional image
    page2 = doc.new_page(width=612, height=792)
    page2.insert_text((72, 100), "Section 2: Results", fontsize=16)

    if with_image:
        # Create a small PNG in memory (100x80 red rectangle)
        img_doc = pymupdf.open()
        img_page = img_doc.new_page(width=100, height=80)
        shape = img_page.new_shape()
        shape.draw_rect(pymupdf.Rect(0, 0, 100, 80))
        shape.finish(color=(1, 0, 0), fill=(1, 0, 0))
        shape.commit()
        pix = img_page.get_pixmap()
        img_bytes = pix.tobytes("png")
        img_doc.close()

        # Insert image into page 2
        rect = pymupdf.Rect(72, 150, 272, 310)
        page2.insert_image(rect, stream=img_bytes)

    doc.save(str(path))
    doc.close()


class TestRealExtraction:
    """End-to-end extraction using real PyMuPDF."""

    def test_real_extraction_markdown_and_figures(self, tmp_path: Path) -> None:
        """Full extraction: markdown + figures from a real PDF."""
        pdf = tmp_path / "paper.pdf"
        _create_test_pdf(pdf, with_image=True)

        out = tmp_path / "extracted"
        result = extract_pdf(pdf, out)

        # Check result type
        assert isinstance(result, ExtractionResult)

        # Check content.md
        md_path = Path(result.markdown_path)
        assert md_path.exists()
        content = md_path.read_text()
        assert "Title of the Paper" in content or len(content) > 0

        # Check page count
        assert result.page_count == 2

        # Check figures
        assert len(result.figures) >= 1
        for fig in result.figures:
            fig_path = out / "figures" / fig.filename
            assert fig_path.exists()
            assert fig_path.stat().st_size > 0

    def test_real_extraction_no_images(self, tmp_path: Path) -> None:
        """Extraction of a PDF with no images — figures list is empty."""
        pdf = tmp_path / "text_only.pdf"
        _create_test_pdf(pdf, with_image=False)

        out = tmp_path / "extracted"
        result = extract_pdf(pdf, out)

        assert result.figures == []
        assert Path(result.markdown_path).exists()
        assert result.page_count == 2

    def test_real_extraction_default_output_dir(self, tmp_path: Path) -> None:
        """Default output dir = {stem}/ next to the PDF."""
        pdf = tmp_path / "mydoc.pdf"
        _create_test_pdf(pdf, with_image=False)

        result = extract_pdf(pdf)

        expected_dir = tmp_path / "mydoc"
        assert result.output_dir == str(expected_dir)
        assert expected_dir.is_dir()
        assert (expected_dir / "content.md").exists()


class TestBibExtractTool:
    """Functional test for BibExtractTool (AXM tool wrapper)."""

    def test_tool_name(self) -> None:
        """Tool name is 'bib_extract'."""
        tool = BibExtractTool()
        assert tool.name == "bib_extract"

    def test_tool_execute_success(self, tmp_path: Path) -> None:
        """Tool wraps extract_pdf and returns ToolResult."""
        pdf = tmp_path / "test.pdf"
        _create_test_pdf(pdf, with_image=True)

        tool = BibExtractTool()
        result = tool.execute(pdf_path=str(pdf), output_dir=str(tmp_path / "out"))

        assert result.success is True
        assert "markdown_path" in result.data
        assert Path(result.data["markdown_path"]).exists()

    def test_tool_execute_missing_path(self) -> None:
        """Empty pdf_path → success=False."""
        tool = BibExtractTool()
        result = tool.execute(pdf_path="")
        assert result.success is False
