"""Inspect one public paper and release metadata, without downloading datasets.

Python 3.9+; standard library only. Optionally set S2_API_KEY in the environment.
Run: python3 semantic-scholar-inspect.py > observation.json
Data source: Semantic Scholar, https://www.semanticscholar.org/product/api
API terms: https://www.semanticscholar.org/product/api/license
"""
import datetime
import json
import os
import sys
import time
import urllib.error
import urllib.parse
import urllib.request

BASE = "https://api.semanticscholar.org"
PAPER_ID = "cb92a7f9d9dbcf9145e32fdfa0e70e2a6b828eb1"
FIELDS = "title,year,externalIds,corpusId,publicationDate,openAccessPdf"


class NoRedirect(urllib.request.HTTPRedirectHandler):
    def redirect_request(self, req, fp, code, msg, headers, newurl):
        return None  # Do not forward an optional API key to a redirect target.


def read_json(path):
    headers = {"User-Agent": "Hyoyoul-S2-Paper-Study/1.0"}
    key = os.environ.get("S2_API_KEY")
    if key:
        headers["x-api-key"] = key
    request = urllib.request.Request(BASE + path, headers=headers)
    opener = urllib.request.build_opener(NoRedirect())
    with opener.open(request, timeout=20) as response:
        data = response.read(2_000_001)
        if len(data) > 2_000_000:
            raise ValueError("Response exceeds the example's 2 MB limit")
        return json.loads(data)


def main():
    paper_path = "/graph/v1/paper/" + PAPER_ID + "?" + urllib.parse.urlencode({"fields": FIELDS})
    paper = read_json(paper_path)
    time.sleep(1.1)  # Two sequential calls; a shared quota can still return 429.
    release = read_json("/datasets/v1/release/latest")
    result = {
        "source": "Semantic Scholar",
        "observedAt": datetime.datetime.now(datetime.timezone.utc).isoformat(),
        "requestedPaperId": PAPER_ID,
        "paperSourceUrl": BASE + paper_path,
        "paper": paper,
        "releaseSourceUrl": BASE + "/datasets/v1/release/" + release["release_id"],
        "releaseId": release["release_id"],
        "datasetNames": sorted(dataset["name"] for dataset in release["datasets"]),
        "scope": "Live paper lookup and release metadata are separate observations, not one consistent snapshot.",
    }
    print(json.dumps(result, ensure_ascii=False, indent=2))


if __name__ == "__main__":
    try:
        main()
    except urllib.error.HTTPError as error:
        # Do not print response bodies, request headers, or credentials.
        wait = error.headers.get("Retry-After")
        print(f"HTTP {error.code}. Retry-After: {wait or 'not supplied'}. No automatic retry.", file=sys.stderr)
        sys.exit(1)
    except (urllib.error.URLError, TimeoutError, ValueError, KeyError) as error:
        print(f"Inspection failed: {type(error).__name__}. No result was fabricated.", file=sys.stderr)
        sys.exit(1)
