"""Can the country endpoint say whether the May 2024 break is American?

The main analysis says the pageview API has no country split. That is loose:
there IS `/metrics/pageviews/top-per-country/{country}/{access}/{y}/{m}/{d}`,
but it returns the fifty most-read ARTICLES in that country on that day, with
views rounded up (`views_ceil`), not a country total. So it cannot give a
country's traffic — but it can give the traffic to that country's fifty most-read
articles, and a step change in one month in one country would still show.

What this measures, stated plainly: **the sum of `views_ceil` over the en.wikipedia
articles in a country's daily top fifty**, on the 15th of each month. It moves
when total reading moves, and it also moves when reading concentrates or spreads
across articles, or when a big news day lands on the 15th. It is a proxy with
known slack, and the point of running it is to see whether the slack is small
enough for a one-month step to be visible at all.

    python research/wikipedia-traffic/country.py

Caches every response under ~/data/wikipedia-traffic/country/.
"""

import json
import os
import sys
import time
import urllib.error
import urllib.request

UA = "Vesper/1.0 (https://untilnextsession.com; vesper@untilnextsession.com)"
CACHE = os.path.expanduser("~/data/wikipedia-traffic/country")
URL = ("https://wikimedia.org/api/rest_v1/metrics/pageviews/top-per-country"
       "/{c}/all-access/{y}/{m:02d}/{d:02d}")

COUNTRIES = ["US", "GB", "IN", "CA", "AU", "DE", "FR", "JP"]
DAY = 15
YEARS = range(2022, 2027)


def fetch(country, year, month):
    path = os.path.join(CACHE, "%s-%04d-%02d.json" % (country, year, month))
    if os.path.exists(path):
        with open(path) as fh:
            return json.load(fh)
    url = URL.format(c=country, y=year, m=month, d=DAY)
    req = urllib.request.Request(url, headers={"User-Agent": UA})
    try:
        with urllib.request.urlopen(req, timeout=45) as fh:
            data = json.loads(fh.read().decode("utf-8"))
    except urllib.error.HTTPError as exc:
        data = {"error": exc.code}
    except Exception as exc:                        # network, once in a while
        data = {"error": str(exc)}
    with open(path, "w") as fh:
        json.dump(data, fh)
    time.sleep(0.15)
    return data


def en_sum(data):
    """Views over the en.wikipedia articles in the country's daily top fifty."""
    items = data.get("items") or []
    if not items:
        return None
    total = 0
    for art in items[0].get("articles", []):
        if art.get("project") == "en.wikipedia":
            total += int(art.get("views_ceil", 0))
    return total or None


def main():
    os.makedirs(CACHE, exist_ok=True)
    months = [(y, m) for y in YEARS for m in range(1, 13)
              if not (y == 2026 and m > 8)]
    table = {}
    for country in COUNTRIES:
        table[country] = {}
        for y, m in months:
            v = en_sum(fetch(country, y, m))
            if v:
                table[country]["%04d-%02d" % (y, m)] = v
        print("%s: %d months" % (country, len(table[country])), file=sys.stderr)

    keys = sorted({k for c in table.values() for k in c})
    print("\nSum of views_ceil over en.wikipedia articles in the daily top fifty,")
    print("the 15th of each month. Year-over-year change, per country.\n")
    head = "month   " + "".join("%7s" % c for c in COUNTRIES)
    print(head)
    for k in keys:
        if k < "2023-01":
            continue
        prev = "%d-%s" % (int(k[:4]) - 1, k[5:])
        cells = ""
        for c in COUNTRIES:
            a, b = table[c].get(prev), table[c].get(k)
            cells += "%7s" % ("%+.0f%%" % (100 * (b / a - 1)) if a and b else "-")
        mark = "  <<< AI Overviews" if k == "2024-05" else ""
        print("%s%s%s" % (k, cells, mark))

    out = os.path.join(os.path.dirname(os.path.abspath(__file__)), "country.csv")
    with open(out, "w") as fh:
        fh.write("month," + ",".join(COUNTRIES) + "\n")
        for k in keys:
            fh.write(k + "," + ",".join(str(table[c].get(k, "")) for c in COUNTRIES) + "\n")
    print("\nwrote", out)
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
