"""BibResolveTool — resolve exact scholarly identifiers to BibTeX.

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

from __future__ import annotations

from typing import Any

from axm.tools.base import AXMTool, ToolResult

from axm_bib.merge import check_coherence, merge_entries
from axm_bib.pipeline import BibPipeline
from axm_bib.resolver import IdentifierType, detect_identifier

__all__ = ["BibResolveTool"]


class BibResolveTool(AXMTool):
    """Resolve exact scholarly identifiers to a BibTeX entry.

    Accepts DOI, arXiv ID, HAL ID, DBLP key, or OpenReview URL.
    Rejects plain titles — use ``bib_search`` for discovery.

    Single ref: resolve directly.
    Multiple refs (same paper): resolve each, check coherence, merge.

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

    @property
    def name(self) -> str:
        """Return the MCP tool name."""
        return "bib_resolve"

    @staticmethod
    def _validate_refs(
        ref: str,
        refs: list[str] | None,
    ) -> list[str] | ToolResult:
        """Validate and normalize input identifiers.

        Returns:
            Deduped list of identifiers, or ToolResult on validation error.
        """
        id_list = refs if refs else ([ref] if ref.strip() else [])
        if not id_list:
            return ToolResult(
                success=False,
                error="identifier is required (ref or refs)",
            )

        # Dedup preserving order
        id_list = list(dict.fromkeys(id_list))

        # Reject titles early
        for r in id_list:
            id_type, _ = detect_identifier(r)
            if id_type == IdentifierType.TITLE:
                return ToolResult(
                    success=False,
                    error=(
                        f"'{r}' looks like a title, not an identifier. "
                        "Use bib_search to discover papers, then resolve "
                        "by DOI or arXiv ID."
                    ),
                )
        return id_list

    def execute(
        self,
        *,
        ref: str = "",
        refs: list[str] | None = None,
        **kwargs: Any,
    ) -> ToolResult:
        """Resolve identifier(s) to BibTeX.

        Args:
            ref: Single scholarly identifier (DOI, arXiv ID, etc.).
            refs: Multiple identifiers for the *same* paper to merge.
                Supply either ``ref`` or ``refs``, not both.

        Returns:
            ToolResult with data={"bibtex": ..., "key": ..., "doi": ...}.
        """
        validated = self._validate_refs(ref, refs)
        if isinstance(validated, ToolResult):
            return validated

        try:
            pipeline = BibPipeline()
            entries = [pipeline.resolve(r) for r in validated]

            if len(entries) == 1:
                entry = entries[0]
            else:
                if not check_coherence(entries):
                    return ToolResult(
                        success=False,
                        error=(
                            "Identifiers refer to different papers. "
                            "Cannot merge incoherent entries."
                        ),
                    )
                entry = merge_entries(entries)

            return ToolResult(
                success=True,
                data={
                    "bibtex": entry.raw,
                    "key": entry.key,
                    "doi": entry.doi,
                    "entry_type": entry.entry_type,
                },
            )
        except Exception as exc:
            return ToolResult(success=False, error=str(exc))
