import json

from fastmcp import Context, FastMCP

from mcsci_hub.clients.crossref import CrossRefClient
from mcsci_hub.clients.semantic_scholar import SemanticScholarClient
from mcsci_hub.models import BibTeXResult


def _construct_bibtex_from_crossref(doi: str, item: dict) -> str:
    """Build a BibTeX entry from CrossRef metadata when S2 doesn't have one."""
    authors = CrossRefClient.parse_authors(item)
    title = CrossRefClient.parse_title(item)
    year = CrossRefClient.parse_year(item)
    journal = CrossRefClient.parse_journal(item)
    volume = item.get("volume", "")
    pages = item.get("page", "")

    # Generate cite key: FirstAuthorLastName + Year
    cite_key = "unknown"
    if authors:
        last_name = authors[0].split()[-1].lower() if authors[0] else "unknown"
        cite_key = f"{last_name}{year}" if year else last_name

    author_str = " and ".join(authors)

    lines = [f"@article{{{cite_key},"]
    if title:
        lines.append(f"  title = {{{title}}},")
    if author_str:
        lines.append(f"  author = {{{author_str}}},")
    if year:
        lines.append(f"  year = {{{year}}},")
    if journal:
        lines.append(f"  journal = {{{journal}}},")
    if volume:
        lines.append(f"  volume = {{{volume}}},")
    if pages:
        lines.append(f"  pages = {{{pages}}},")
    lines.append(f"  doi = {{{doi}}},")
    lines.append("}")
    return "\n".join(lines)


def register(mcp: FastMCP) -> None:
    @mcp.tool()
    async def get_bibtex(ctx: Context, doi: str) -> str:
        """Get a ready-to-paste BibTeX citation entry for a paper.

        Tries Semantic Scholar's pre-formatted BibTeX first, then constructs
        one from CrossRef metadata as a fallback. The result can be directly
        pasted into a .bib file for LaTeX/BibTeX workflows.

        Args:
            doi: The DOI of the paper, e.g. '10.1038/nature12373'
        """
        state = ctx.request_context.lifespan_context
        s2: SemanticScholarClient = state["s2"]
        crossref: CrossRefClient = state["crossref"]

        # Try S2 first — has pre-formatted BibTeX
        s2_paper = await s2.get_paper(doi)
        if s2_paper:
            bibtex = SemanticScholarClient.get_bibtex(s2_paper)
            if bibtex:
                return json.dumps(BibTeXResult(
                    doi=doi, bibtex=bibtex, source="semantic_scholar",
                ).model_dump(), indent=2)

        # Fall back to constructing from CrossRef
        cr_work = await crossref.get_work(doi)
        if cr_work:
            bibtex = _construct_bibtex_from_crossref(doi, cr_work)
            return json.dumps(BibTeXResult(
                doi=doi, bibtex=bibtex, source="crossref",
            ).model_dump(), indent=2)

        return json.dumps({
            "error": f"Could not generate BibTeX for DOI: {doi}",
            "doi": doi,
        }, indent=2)
