"""Résolution `url_normalized` → `pages.id` : le point d'extension du module Crawl.

Amendement I4 de la spec (§3.8, §3.9) : la table `pages` **appartient au module Crawl** et
n'existe pas encore. La spec fige néanmoins son mini-contrat (`id`, `url_normalized` unique
par cible, rattachement à la cible, statut HTTP lisible) et demande que la jointure soit
**encapsulée dès T2**, non branchée — pour que T6 ait un seul endroit à ouvrir, et pour que
le pipeline soit écrit contre elle dès aujourd'hui plutôt que rétrofité plus tard.

Aujourd'hui, `resolve_page_ids` est donc un **no-op propre** : elle rend un dictionnaire
vide, `keyword_page_map.page_id` reste `NULL`, et tout ce qui arrive avant le crawl est
« en attente de crawl » — un état de premier rang, jamais une erreur (§0). Rien n'est
bloqué : le job `map_reconcile` de T6 rattrape l'intégralité des maps en attente, quel que
soit l'ordre d'arrivée (invariant de convergence, §3.9).

Le jour où `pages` existe, la fonction le **dit** au lieu de rester muette : le pipeline
continuerait sinon à écrire des `page_id` NULL sans que personne ne s'en aperçoive, et le
rattrapage ne viendrait que du reconcile. Un avertissement au démarrage du premier import
est le bon compromis : bruyant pour l'équipe, inoffensif pour l'import en cours.
"""

import logging
import uuid
from collections.abc import Collection

from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession

logger = logging.getLogger(__name__)

# Mini-contrat §3.8 : le nom de la table que posera la migration du module Crawl.
PAGES_TABLE = "pages"


async def pages_available(session: AsyncSession) -> bool:
    """`True` quand la table `pages` du module Crawl existe dans la base."""
    return await session.scalar(select(func.to_regclass(PAGES_TABLE))) is not None


async def resolve_page_ids(
    session: AsyncSession, site_target_id: uuid.UUID, urls: Collection[str]
) -> dict[str, uuid.UUID]:
    """Les `page_id` connus de la cible pour ces URL normalisées.

    Contrat figé (§3.8) : la clé est l'`url_normalized` produit par `app.core.urls`, la
    valeur est l'`id` de la page. Une URL absente du résultat garde `page_id = NULL` — c'est
    la planification d'une page pas encore publiée, jamais une erreur.
    """
    if not urls:
        return {}
    if not await pages_available(session):
        return {}
    logger.warning(
        "table `%s` présente : la résolution de l'attache à l'insertion n'est pas branchée "
        "(T6). Les maps restent en attente jusqu'au prochain `map_reconcile`.",
        PAGES_TABLE,
    )
    return {}
