"""BibGraphTool — citation graph traversal via S2 + OpenAlex fallback.

Registered as ``bib_graph`` via ``axm.tools`` entry point.
"""

from __future__ import annotations

from typing import Any

from axm.tools.base import AXMTool, ToolResult

from axm_bib.pipeline import BibPipeline

__all__ = ["BibGraphTool"]

_VALID_DIRECTIONS = frozenset({"citations", "references", "similar"})


class BibGraphTool(AXMTool):
    """Traverse the citation graph for a paper.

    Registered as 'bib_graph' via axm.tools entry point.
    """

    @property
    def name(self) -> str:
        """Return the tool name used for entry-point registration."""
        return "bib_graph"

    def execute(
        self,
        *,
        paper_id: str = "",
        direction: str = "citations",
        limit: int = 20,
        **kwargs: Any,
    ) -> ToolResult:
        """Traverse the citation graph for a paper.

        Args:
            paper_id: Paper identifier (DOI, arXiv ID, or S2 paper ID).
            direction: One of ``citations``, ``references``, ``similar``.
            limit: Maximum number of results.

        Returns:
            ToolResult with data={"papers": [...], "count": N}.
        """
        if not paper_id.strip():
            return ToolResult(success=False, error="paper_id is required")

        if direction not in _VALID_DIRECTIONS:
            return ToolResult(
                success=False,
                error=(
                    f"invalid direction '{direction}', "
                    f"must be one of: {', '.join(sorted(_VALID_DIRECTIONS))}"
                ),
            )

        try:
            pipeline = BibPipeline()
            papers = pipeline.graph(paper_id, direction=direction, limit=limit)
            return ToolResult(
                success=True,
                data={
                    "papers": [p.model_dump() for p in papers],
                    "count": len(papers),
                },
                hint=(
                    "Tip: Use bib_resolve(ref) for BibTeX, "
                    "or bib_pdf(doi) for full text."
                ),
            )
        except Exception as exc:
            return ToolResult(success=False, error=str(exc))
