"""Garde-fou des commandes de dev qui touchent la base DATA.

`app.db_reset` (destructrice) et `app.seed` refusent de tourner contre autre chose qu'un
Postgres local. Le contrôle se fait sur l'URL, avant toute connexion.
"""

from urllib.parse import parse_qs, urlsplit

# `urlsplit(...).hostname` rend une IPv6 sans crochets : `[::1]` devient `::1`.
# Pendant de `web/lib/db/guard.ts`, qui garde la base AUTH (Node rend `[::1]`, d'où sa liste).
LOCAL_HOSTS = frozenset({"localhost", "127.0.0.1", "::1"})

# asyncpg fait `opts.update(url.query)` : ces paramètres l'emportent sur l'hôte de l'URL et
# rendraient le contrôle d'hôte inopérant.
FORBIDDEN_QUERY_KEYS = ("host", "hostaddr")


def assert_local(url: str) -> None:
    """Lève `RuntimeError` en nommant le fautif si `url` ne pointe pas sur un Postgres local."""
    parts = urlsplit(url)
    if parts.hostname not in LOCAL_HOSTS:
        raise RuntimeError(f"Refus : DATABASE_URL pointe sur {parts.hostname!r}, pas sur localhost")
    query = parse_qs(parts.query, keep_blank_values=True)
    for key in FORBIDDEN_QUERY_KEYS:
        if key in query:
            raise RuntimeError(
                f"Refus : DATABASE_URL passe {key}={query[key][0]!r} en query string, "
                "qui l'emporte sur l'hôte de l'URL"
            )
