"""Unit tests for BibExtractTool — input validation + error paths."""

from __future__ import annotations

from unittest.mock import MagicMock, patch

from axm.tools.base import ToolResult

from axm_bib.models import ExtractionResult, FigureInfo
from axm_bib.tools.bib_extract import BibExtractTool


class TestBibExtractToolValidation:
    """Input validation tests."""

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

    def test_whitespace_pdf_path(self) -> None:
        """Whitespace-only pdf_path → success=False."""
        tool = BibExtractTool()
        result = tool.execute(pdf_path="   ")
        assert result.success is False
        assert result.error == "pdf_path is required"


class TestBibExtractToolSuccess:
    """Successful execution (mocked extract_pdf)."""

    @patch("axm_bib.tools.bib_extract.extract_pdf")
    def test_success_no_figures(self, mock_extract: MagicMock) -> None:
        """Extract PDF with no figures."""
        mock_extract.return_value = ExtractionResult(
            source_pdf="/tmp/paper.pdf",
            output_dir="/tmp/out",
            markdown_path="/tmp/out/content.md",
            figures=[],
            page_count=5,
            word_count=3000,
            char_count=18000,
        )
        tool = BibExtractTool()
        result = tool.execute(pdf_path="/tmp/paper.pdf")
        assert result.success is True
        assert result.data["page_count"] == 5
        assert result.data["word_count"] == 3000
        assert result.data["figure_count"] == 0
        assert result.data["figures"] == []

    @patch("axm_bib.tools.bib_extract.extract_pdf")
    def test_success_with_figures(self, mock_extract: MagicMock) -> None:
        """Extract PDF with figures."""
        mock_extract.return_value = ExtractionResult(
            source_pdf="/tmp/paper.pdf",
            output_dir="/tmp/out",
            markdown_path="/tmp/out/content.md",
            figures=[
                FigureInfo(
                    index=1,
                    filename="fig_001.png",
                    page=2,
                    width=640,
                    height=480,
                    xref=10,
                ),
            ],
            page_count=10,
            word_count=5000,
            char_count=30000,
        )
        tool = BibExtractTool()
        result = tool.execute(pdf_path="/tmp/paper.pdf")
        assert result.data["figure_count"] == 1
        assert result.data["figures"][0]["filename"] == "fig_001.png"
        assert result.data["figures"][0]["page"] == 2

    @patch("axm_bib.tools.bib_extract.extract_pdf")
    def test_custom_output_dir(self, mock_extract: MagicMock) -> None:
        """Custom output_dir is passed to extract_pdf."""
        mock_extract.return_value = ExtractionResult(
            source_pdf="/tmp/paper.pdf",
            output_dir="/custom/out",
            markdown_path="/custom/out/content.md",
            figures=[],
            page_count=1,
            word_count=100,
            char_count=600,
        )
        tool = BibExtractTool()
        result = tool.execute(pdf_path="/tmp/paper.pdf", output_dir="/custom/out")
        assert result.success is True
        assert result.data["output_dir"] == "/custom/out"

    @patch("axm_bib.tools.bib_extract.extract_pdf")
    def test_result_is_tool_result(self, mock_extract: MagicMock) -> None:
        """Return type is ToolResult."""
        mock_extract.return_value = ExtractionResult(
            source_pdf="/tmp/p.pdf",
            output_dir="/tmp/o",
            markdown_path="/tmp/o/c.md",
            figures=[],
            page_count=1,
            word_count=0,
            char_count=0,
        )
        tool = BibExtractTool()
        result = tool.execute(pdf_path="/tmp/p.pdf")
        assert isinstance(result, ToolResult)


class TestBibExtractToolErrors:
    """Error handling tests."""

    @patch("axm_bib.tools.bib_extract.extract_pdf")
    def test_file_not_found(self, mock_extract: MagicMock) -> None:
        """FileNotFoundError → success=False."""
        mock_extract.side_effect = FileNotFoundError("No such file")
        tool = BibExtractTool()
        result = tool.execute(pdf_path="/nonexistent.pdf")
        assert result.success is False
        assert "No such file" in result.error  # type: ignore[operator]

    @patch("axm_bib.tools.bib_extract.extract_pdf")
    def test_generic_exception(self, mock_extract: MagicMock) -> None:
        """Generic exception → success=False with error."""
        mock_extract.side_effect = Exception("Corrupt PDF")
        tool = BibExtractTool()
        result = tool.execute(pdf_path="/tmp/bad.pdf")
        assert result.success is False
        assert "Corrupt PDF" in result.error  # type: ignore[operator]


class TestBibExtractToolNameProperty:
    """Tool name registration."""

    def test_name_is_bib_extract(self) -> None:
        """Tool name property returns 'bib_extract'."""
        assert BibExtractTool().name == "bib_extract"
