"""Wikidata API."""

import json
import typing
from typing import cast

import requests
import simplejson.errors

from . import CallParams, user_agent_headers

wd_api_url = "https://www.wikidata.org/w/api.php"

Claims = dict[str, list[dict[str, typing.Any]]]
Sitelinks = dict[str, dict[str, typing.Any]]


class EntityType(typing.TypedDict, total=False):
    """Wikidata Entity."""

    id: str
    ns: str
    type: str
    pageid: int
    title: str
    labels: dict[str, typing.Any]
    descriptions: dict[str, typing.Any]
    claims: Claims
    lastrevid: int
    sitelinks: Sitelinks
    modified: str
    redirects: dict[str, typing.Any]
    aliases: dict[str, list[dict[str, typing.Any]]]


def api_get(params: CallParams) -> requests.Response:
    """Call the wikidata API."""
    call_params: CallParams = {
        "format": "json",
        "formatversion": 2,
        **params,
    }

    r = requests.get(wd_api_url, params=call_params, headers=user_agent_headers())
    return r


def get_revision_timestamp(revid: int) -> str:
    """Get timetsmap for the given revid."""
    params: CallParams = {
        "action": "query",
        "prop": "revisions",
        "revids": revid,
        "rvprop": "ids|timestamp",
    }
    r = api_get(params)
    rev = r.json()["query"]["pages"][0]["revisions"][0]
    assert rev["revid"] == int(revid)
    return cast(str, rev["timestamp"])


def get_recent_changes(
    rcstart: str | None = None, rccontinue: str | None = None
) -> requests.Response:
    """Get list of recent changes."""
    props = [
        "title",
        "ids",
        "comment",
        "parsedcomment",
        "timestamp",
        "redirect",
        "loginfo",
    ]

    params: CallParams = {
        "action": "query",
        "list": "recentchanges",
        "rcnamespace": 0,
        "rclimit": "max",
        "rcdir": "newer",
        "rcprop": "|".join(props),
    }
    if rcstart is not None:
        params["rcstart"] = rcstart
    if rccontinue is not None:
        params["rccontinue"] = rccontinue

    return api_get(params)


def get_entity(qid: str) -> EntityType:
    """Retrieve a Wikidata item with the given QID using the API."""
    r = api_get({"action": "wbgetentities", "ids": qid})
    try:
        data = r.json()
    except simplejson.errors.JSONDecodeError:
        print(r.text)
        raise
    if "entities" not in data:
        print(json.dumps(data, indent=2))
    return cast(EntityType, data["entities"][qid])


def get_entities(ids: list[str]) -> typing.Iterator[tuple[str, EntityType]]:
    """Get Wikidata item entities with the given QIDs."""
    r = api_get({"action": "wbgetentities", "ids": "|".join(ids)})
    return ((qid, entity) for qid, entity in r.json()["entities"].items())