#!/usr/bin/env python3
"""Lataa Google Fonts -CSS:n woff2-tiedostot paikalliseen kansioon
ja kirjoittaa CSS:n, jossa src: url() osoittaa paikallisiin tiedostoihin.

Clauden tuottama =)

Käyttö:
    python3 fontit_local.py fonts.css                  # -> fonts.local.css, ./fontit/
    python3 fontit_local.py fonts.css -o out.css -d fontit
    python3 fontit_local.py fonts.css --prefix /static/fontit
"""
import time
import argparse
import re
import sys
import urllib.request
from pathlib import Path
from urllib.parse import urlparse

URL_RE = re.compile(r"url\(\s*(['\"]?)(https?://[^)'\"]+\.woff2)\1\s*\)")
FACE_RE = re.compile(r"/\*\s*([\w-]+)\s*\*/\s*@font-face\s*\{(.*?)\}", re.S)


def fetch(url: str, dest: Path) -> None:
    if dest.exists() and dest.stat().st_size > 0:
        return
    req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
    with urllib.request.urlopen(req, timeout=30) as r:
        dest.write_bytes(r.read())


def field(block: str, name: str, default: str = "") -> str:
    m = re.search(rf"{name}\s*:\s*([^;]+);", block)
    return m.group(1).strip().strip("'\"") if m else default


def main() -> int:
    ap = argparse.ArgumentParser()
    ap.add_argument("input", help="CSS-tiedosto")
    ap.add_argument("-o", "--output", help="tulostiedosto (oletus: <input>.local.css)")
    ap.add_argument("-d", "--dir", default="src", help="fonttikansio (oletus: src)")
    ap.add_argument("--prefix", help="url()-polun etuliite CSS:ssä (oletus: ./<dir>)")
    args = ap.parse_args()

    src = Path(args.input)
    css = src.read_text(encoding="utf-8")
    out_path = Path(args.output) if args.output else src.with_suffix(".local.css")
    font_dir = Path(args.dir)
    font_dir.mkdir(parents=True, exist_ok=True)
    prefix = (args.prefix or f"./{args.dir}").rstrip("/")

    used: dict[str, str] = {}  # url -> paikallinen tiedostonimi

    def local_name(url: str, block: str) -> str:
        if url in used:
            return used[url]
        family = field(block, "font-family").replace(" ", "")
        style = field(block, "font-style", "normal")
        subset = block_subset.get(id(block), "")
        base = f"{family}-{style}-{subset}".strip("-") if subset else Path(urlparse(url).path).stem
        name = f"{base}.woff2"
        # varmista yksikäsitteisyys
        existing = set(used.values())
        if name in existing:
            name = f"{base}-{Path(urlparse(url).path).stem}.woff2"
        used[url] = name
        return name

    block_subset: dict[int, str] = {}

    def repl_face(m: re.Match) -> str:
        subset, body = m.group(1), m.group(2)
        block_subset[id(body)] = subset


        t = time.time()

        def repl_url(um: re.Match) -> str:
            url = um.group(2)
            name = local_name(url, body)
            dest = font_dir / name
            try:
                print(f"lataa {url} -> {dest}")
                fetch(url, dest)
            except Exception as e:  # noqa: BLE001
                print(f"VIRHE {url}: {e}", file=sys.stderr)
                return um.group(0)
            return f"url({prefix}/{name}?t{t})"

        new_body = URL_RE.sub(repl_url, body)
        return f"/* {subset} */\n@font-face {{{new_body}}}"

    new_css = FACE_RE.sub(repl_face, css)
    out_path.write_text(new_css, encoding="utf-8")
    print(f"\nvalmis: {out_path} ({len(used)} fonttia kansiossa {font_dir}/)")
    return 0


if __name__ == "__main__":
    sys.exit(main())
