"""Server-side citation hydration.

The LLM only emits markers like `[Doc 1]`. We collect the actual
`public_document_id`s from tool observations, look up the matching
`Document` rows (re-applying `for_user`), and produce a list of
`{public_document_id, title, url, document_uid}` entries that the UI
renders as chips. The LLM never produces clickable URLs directly, so it
cannot hallucinate links to documents that don't exist or aren't visible.
"""
from __future__ import annotations

from typing import Iterable

from django.urls import reverse


def hydrate_citations(public_document_ids: Iterable[str], user) -> list[dict]:
    pids = [p for p in dict.fromkeys(public_document_ids) if p]
    if not pids:
        return []
    from apps.repository.documents.models import Document

    visible = list(
        Document.objects.for_user(user)
        .filter(public_document_id__in=pids)
        .only("title", "public_document_id", "document_uid")
    )
    by_pid = {d.public_document_id: d for d in visible}
    out: list[dict] = []
    for pid in pids:
        d = by_pid.get(pid)
        if not d:
            continue
        try:
            url = reverse("repo_documents:document_detail", kwargs={"uid": d.document_uid})
        except Exception:  # noqa: BLE001 — never let URL reverse break a turn
            url = ""
        out.append({
            "public_document_id": d.public_document_id,
            "document_uid": str(d.document_uid),
            "title": d.title,
            "url": url,
        })
    return out
