"""Parse the user-facing `kind:name` shortcut used by the add-tag input.

Mirrors IR's app/utils/tag_prefix.py. Tag.name in FC is stored bare;
the `kind:` prefix only exists as an input convention at user-facing
places (image-modal add-tag input, future bulk-add forms). The parser
is the single owner of the kind-string list — anything not in
KNOWN_KINDS keeps its colon as literal text.
"""

from __future__ import annotations

# Kinds the user can type as a prefix at the input boundary.
# Exclusions:
#   - `general` is the default for un-prefixed input (never typed as prefix)
#   - `archive`, `post` are system-managed
#   - `artist` was retired in FC-2d-vii-c — artists are first-class
#     entities (Artist row + ImageRecord.artist_id), browsed via the
#     provenance axis rather than as tags. See project_provenance_separation.
#   - `meta`, `rating` retired as user-typeable per operator 2026-05-26 —
#     content classification only needs character/fandom/series.
KNOWN_KINDS: frozenset[str] = frozenset({
    "character",
    "fandom",
    "series",
})


def parse_kind_prefix(raw: str) -> tuple[str | None, str]:
    """Split a raw user-typed tag string into (kind, name).

    Returns (kind, name) where kind is lowercase canonical and in
    KNOWN_KINDS, or (None, raw.strip()) if no recognized prefix is
    present. `name` is always whitespace-stripped.

    Examples:
        parse_kind_prefix("character:Saber") -> ("character", "Saber")
        parse_kind_prefix("Character:Saber") -> ("character", "Saber")
        parse_kind_prefix("sunset")          -> (None, "sunset")
        parse_kind_prefix("http://example")  -> (None, "http://example")
        parse_kind_prefix("fandom: FSN ")    -> ("fandom", "FSN")
    """
    if ":" in raw:
        prefix, rest = raw.split(":", 1)
        if prefix.lower() in KNOWN_KINDS:
            return prefix.lower(), rest.strip()
    return None, raw.strip()
