"""Postgres full-text search indexing for Repository documents."""

from __future__ import annotations

from django.contrib.postgres.search import SearchVector


def update_search_vector(document_id: int) -> bool:
    """Rebuild the ``search_vector`` column for a single document.

    Weighting:
        A = title
        B = authors + abstract
        C = extracted full-text body + subjects/keywords + geographic facets
            (country, regions) + bibliographic source (journal / publisher /
            conference)
    """
    from apps.repository.documents.models import Document

    try:
        document = Document.objects.get(pk=document_id)
    except Document.DoesNotExist:
        return False

    # Materialise M2M / facet text first — can't mix annotations with M2M in one SearchVector.
    author_names = " ".join(
        f"{a.first_name} {a.last_name} {a.orcid or ''}".strip()
        for a in document.authors.all()
    )
    facet_terms = " ".join(
        part
        for part in (
            " ".join(document.keywords.values_list("label", flat=True)),
            " ".join(document.regions.values_list("name", flat=True)),
            document.country,
            document.journal_title,
            document.publisher,
            document.conference_name,
        )
        if part
    ).strip()

    vector = (
        SearchVector("title", weight="A")
        + SearchVector("abstract", weight="B")
        + SearchVector("extracted_text", weight="C")
    )

    Document.objects.filter(pk=document.pk).update(search_vector=vector)
    # Fold author names (B) and facet/subject/geo terms (C) into the vector.
    from django.db import connection

    fragments = []
    params = []
    if author_names:
        fragments.append("setweight(to_tsvector('english', %s), 'B')")
        params.append(author_names)
    if facet_terms:
        fragments.append("setweight(to_tsvector('english', %s), 'C')")
        params.append(facet_terms)
    if fragments:
        with connection.cursor() as cur:
            cur.execute(
                "UPDATE repository_documents_document "
                "SET search_vector = COALESCE(search_vector, ''::tsvector) || "
                + " || ".join(fragments)
                + " WHERE id = %s",
                [*params, document.pk],
            )
    return True
