"""External-system ingestion helpers — RIMS payloads, ORCID lookup, DOI resolution."""

from __future__ import annotations

import logging
from typing import Any

import requests

logger = logging.getLogger(__name__)


_ORCID_PUBLIC_API = "https://pub.orcid.org/v3.0"
_CROSSREF_API = "https://api.crossref.org/works"


def parse_rims_payload(payload: dict[str, Any]) -> dict[str, Any]:
    """Normalise a RIMS grant close-out payload into the Repository's internal
    document creation kwargs.

    Expected payload keys (per PRD REPO-SP8):
        researcher_name, orcid, document_type, title, abstract,
        grant_reference, license_type
    """
    required = ("title", "grant_reference", "document_type")
    missing = [k for k in required if not payload.get(k)]
    if missing:
        raise ValueError(f"RIMS payload missing required fields: {missing}")

    return {
        "title": payload["title"].strip()[:400],
        "abstract": (payload.get("abstract") or "").strip(),
        "document_type": payload["document_type"],
        "grant_reference": payload["grant_reference"].strip(),
        "license_type": payload.get("license_type", "cc_by"),
        "language": payload.get("language", "en"),
        "year": payload.get("year"),
        "authors": [
            {
                "name": (payload.get("researcher_name") or "").strip(),
                "orcid": (payload.get("orcid") or "").strip() or None,
            }
        ],
    }


def lookup_orcid(orcid: str, *, timeout: float = 5.0) -> dict[str, Any] | None:
    """Best-effort lookup against the public ORCID API; returns minimal author info."""
    if not orcid:
        return None
    url = f"{_ORCID_PUBLIC_API}/{orcid}/person"
    try:
        resp = requests.get(url, headers={"Accept": "application/json"}, timeout=timeout)
        if resp.status_code != 200:
            return None
        data = resp.json()
        name = data.get("name", {}) or {}
        given = (name.get("given-names") or {}).get("value", "")
        family = (name.get("family-name") or {}).get("value", "")
        emails = ((data.get("emails") or {}).get("email") or [])
        primary_email = emails[0]["email"] if emails else ""
        return {"first_name": given, "last_name": family, "email": primary_email}
    except (requests.RequestException, ValueError, KeyError):
        logger.warning("ORCID lookup failed for %s", orcid, exc_info=True)
        return None


def resolve_doi(doi: str, *, timeout: float = 5.0) -> dict[str, Any] | None:
    """Resolve a DOI through Crossref to enrich title / authors / year."""
    if not doi:
        return None
    try:
        resp = requests.get(f"{_CROSSREF_API}/{doi}", timeout=timeout)
        if resp.status_code != 200:
            return None
        message = (resp.json() or {}).get("message", {}) or {}
        title = (message.get("title") or [""])[0]
        authors = [
            {"first_name": a.get("given", ""), "last_name": a.get("family", "")}
            for a in (message.get("author") or [])
        ]
        year = None
        date_parts = (message.get("issued") or {}).get("date-parts") or [[None]]
        if date_parts and date_parts[0]:
            year = date_parts[0][0]
        return {"title": title, "authors": authors, "year": year}
    except (requests.RequestException, ValueError, KeyError):
        logger.warning("DOI resolution failed for %s", doi, exc_info=True)
        return None
