"""Shared tag-with-fandom query columns + serialization.

Resolving a character tag's fandom NAME via a Tag self-join (Tag.fandom_id -> the
fandom Tag) and serializing the canonical
``{id, name, kind, fandom_id, fandom_name}`` dict were hand-written in
TagService.autocomplete / .list_for_image and GalleryService.get_image_with_tags
(the last two added by the fandom-on-chip feature, 978f49a). One source now
(DRY pattern sweep 2026-06-10) so a new tag field is added in exactly one place.

TagDirectoryService selects the FULL Tag ORM plus an image-count aggregate (a
different select shape), so it keeps its own variant — not folded in here.
"""

from ..models import Tag


def fandom_join_alias():
    """A Tag self-join alias for resolving a tag's fandom name. Outerjoin it on
    ``Tag.fandom_id == <alias>.c.id`` and select via `tag_columns(alias)`."""
    return Tag.__table__.alias("fandom_lookup")


def tag_columns(fandom_alias):
    """The canonical (id, name, kind, fandom_id, fandom_name) column set for a
    tag select that outerjoins `fandom_alias` (from `fandom_join_alias()`)."""
    return [
        Tag.id,
        Tag.name,
        Tag.kind,
        Tag.fandom_id,
        fandom_alias.c.name.label("fandom_name"),
    ]


def serialize_tag(row) -> dict:
    """Serialize a row carrying .id/.name/.kind/.fandom_id/.fandom_name to the
    canonical tag dict. `kind` may be a TagKind enum or a plain string."""
    return {
        "id": row.id,
        "name": row.name,
        "kind": row.kind.value if hasattr(row.kind, "value") else row.kind,
        "fandom_id": row.fandom_id,
        "fandom_name": row.fandom_name,
    }
