#!/usr/bin/env python3
"""Return a structured agent-access receipt for a URL from Gizmo's public catalog."""
from __future__ import annotations

import argparse
import json
import sys
import urllib.error
import urllib.request
from datetime import datetime, timezone
from urllib.parse import urlparse

DEFAULT_CATALOG = "https://gizmo-agent.pages.dev/directory/data.json"


def host(value: str) -> str | None:
    candidate = value if "://" in value else f"https://{value}"
    parsed = urlparse(candidate)
    if parsed.scheme not in {"http", "https"} or not parsed.hostname:
        return None
    return parsed.hostname.casefold().removeprefix("www.")


def fetch_catalog(url: str) -> dict:
    request = urllib.request.Request(url, headers={"User-Agent": "Gizmo-agent-access-receipt/1.0"})
    with urllib.request.urlopen(request, timeout=20) as response:
        if response.status != 200:
            raise ValueError(f"catalog returned HTTP {response.status}")
        document = json.load(response)
    if not isinstance(document, dict) or not isinstance(document.get("services"), list):
        raise ValueError("catalog has no services array")
    return document


def main() -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("url", help="URL or hostname to look up")
    parser.add_argument("--catalog", default=DEFAULT_CATALOG, help="catalog URL (default: public Gizmo catalog)")
    args = parser.parse_args()
    query_host = host(args.url)
    if not query_host:
        print(json.dumps({"error": "url must be an absolute HTTP(S) URL or hostname"}, sort_keys=True))
        return 2
    try:
        catalog = fetch_catalog(args.catalog)
    except (OSError, urllib.error.URLError, ValueError, json.JSONDecodeError) as exc:
        print(json.dumps({"error": f"catalog unavailable: {exc}"}, sort_keys=True))
        return 1
    match = None
    for service in catalog["services"]:
        service_host = host(str(service.get("url", "")))
        if service_host and (query_host == service_host or query_host.endswith(f".{service_host}")):
            match = service
            break
    receipt = {
        "schema_version": "1.0",
        "checked_at_utc": datetime.now(timezone.utc).isoformat(timespec="seconds"),
        "query": args.url,
        "query_host": query_host,
        "catalog": args.catalog,
        "catalog_updated": catalog.get("updated"),
        "matched": match is not None,
        "receipt": match,
    }
    print(json.dumps(receipt, sort_keys=True, ensure_ascii=False))
    return 0


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