import logging
from urllib.parse import quote

import httpx

logger = logging.getLogger(__name__)

BASE_URL = "https://api.semanticscholar.org/graph/v1"

PAPER_FIELDS = ",".join([
    "title",
    "authors",
    "year",
    "venue",
    "abstract",
    "citationCount",
    "influentialCitationCount",
    "isOpenAccess",
    "openAccessPdf",
    "fieldsOfStudy",
    "citationStyles",
    "externalIds",
    "publicationTypes",
    "journal",
    "volume",
])

CITATION_FIELDS = ",".join([
    "title",
    "authors",
    "year",
    "venue",
    "citationCount",
    "isInfluential",
    "externalIds",
])


class SemanticScholarClient:
    def __init__(self, http_client: httpx.AsyncClient, api_key: str = ""):
        self._client = http_client
        self._api_key = api_key

    def _headers(self) -> dict[str, str]:
        headers: dict[str, str] = {}
        if self._api_key:
            headers["x-api-key"] = self._api_key
        return headers

    async def get_paper(self, doi: str) -> dict | None:
        try:
            resp = await self._client.get(
                f"{BASE_URL}/paper/DOI:{quote(doi, safe='/')}",
                params={"fields": PAPER_FIELDS},
                headers=self._headers(),
            )
            resp.raise_for_status()
            return resp.json()
        except httpx.HTTPError as e:
            logger.warning("Semantic Scholar lookup failed for %s: %s", doi, e)
            return None

    async def get_citations(self, doi: str, max_results: int = 20) -> list[dict]:
        try:
            resp = await self._client.get(
                f"{BASE_URL}/paper/DOI:{quote(doi, safe='/')}/citations",
                params={"fields": CITATION_FIELDS, "limit": max_results},
                headers=self._headers(),
            )
            resp.raise_for_status()
            data = resp.json()
            return data.get("data", [])
        except httpx.HTTPError as e:
            logger.warning("Semantic Scholar citations failed for %s: %s", doi, e)
            return []

    async def get_references(self, doi: str, max_results: int = 20) -> list[dict]:
        try:
            resp = await self._client.get(
                f"{BASE_URL}/paper/DOI:{quote(doi, safe='/')}/references",
                params={"fields": CITATION_FIELDS, "limit": max_results},
                headers=self._headers(),
            )
            resp.raise_for_status()
            data = resp.json()
            return data.get("data", [])
        except httpx.HTTPError as e:
            logger.warning("Semantic Scholar references failed for %s: %s", doi, e)
            return []

    @staticmethod
    def parse_authors(paper: dict) -> list[str]:
        return [a.get("name", "") for a in paper.get("authors", []) if a.get("name")]

    @staticmethod
    def parse_doi(paper: dict) -> str:
        ext = paper.get("externalIds", {})
        return ext.get("DOI", "") or ""

    @staticmethod
    def get_bibtex(paper: dict) -> str:
        styles = paper.get("citationStyles", {})
        return styles.get("bibtex", "") or ""

    @staticmethod
    def get_oa_url(paper: dict) -> str:
        oa = paper.get("openAccessPdf")
        if oa:
            return oa.get("url", "") or ""
        return ""
