"""TopicScanner and TopicLabel enum for meshulash-guard SDK.

TopicScanner detects and acts on text categorized into specific topic categories
by the server's 'topic' TC classification head. Label values are the exact
strings from the server's label_config.json (case-sensitive).
"""

from __future__ import annotations

from typing import Sequence

from ..enums import Action, Condition, _StrValueMixin
from .base import BaseScanner


class TopicLabel(_StrValueMixin):
    """Labels for topic detection.

    Values are the exact strings used by the server's 'topic' TC head.
    Member names are uppercase/underscored for Python ergonomics.
    """

    ALBUM = "Album"
    ANIMAL = "Animal"
    ARTIST = "Artist"
    ATHLETE = "Athlete"
    BUILDING = "Building"
    BUSINESS_FINANCE = "Business & Finance"
    COMPANY = "Company"
    COMPUTERS_INTERNET = "Computers & Internet"
    EDUCATION_REFERENCE = "Education & Reference"
    EDUCATIONAL_INSTITUTION = "EducationalInstitution"
    ENTERTAINMENT_MUSIC = "Entertainment & Music"
    ETHNICITY_RACE = "Ethnicity & Race"
    FAMILY_RELATIONSHIPS = "Family & Relationships"
    FILM = "Film"
    HEALTH = "Health"
    IDENTITY_ATTACK = "Identity_Attack"
    LEGAL_REGULATIONS = "Legal & Regulations"
    MEAN_OF_TRANSPORTATION = "MeanOfTransportation"
    NATURAL_PLACE = "NaturalPlace"
    OFFICE_HOLDER = "OfficeHolder"
    PHILOSOPHICAL_CONCEPT = "Philosophical Concept"
    PLANT = "Plant"
    POLITICS_GOVERNMENT = "Politics & Government"
    SCIENCE_MATHEMATICS = "Science & Mathematics"
    SEXUAL_EXPLICIT = "Sexual_Explicit"
    SOCIETY_CULTURE = "Society & Culture"
    SOFTWARE_DEVELOPMENT_CODE = "Software Development & Code"
    SPORTS = "Sports"
    VILLAGE = "Village"
    WRITTEN_WORK = "WrittenWork"
    ALL = "__ALL__"


class TopicScanner(BaseScanner):
    """Scanner for topic classification.

    Detects text belonging to specified topic categories using the server's
    'topic' TC classification head.

    Args:
        labels: One or more TopicLabel members. Use TopicLabel.ALL to scan
            all topics. Cannot be empty.
        action: Action to take when a topic is detected. Defaults to BLOCK.
        condition: Gating condition (ANY, ALL, K_OF, CONTEXTUAL).
        threshold: Optional confidence threshold (0.0–1.0).
        allowlist: Optional list of values to allow through even if detected.
    """

    _TC_HEAD = "topic"

    def __init__(
        self,
        labels: Sequence[TopicLabel],
        action: Action = Action.BLOCK,
        condition: Condition = Condition.ANY,
        threshold: float | None = None,
        allowlist: list[str] | None = None,
    ) -> None:
        if not labels:
            raise ValueError(
                "TopicScanner requires at least one label. "
                "Use TopicLabel.ALL to scan everything."
            )
        self._labels = list(labels)
        self._action = action
        self._condition = condition
        self._threshold = threshold
        self._allowlist = allowlist or []

    def to_guardline_spec(self) -> dict:
        """Return a guardline spec dict for this scanner configuration."""
        if any(lbl.value == "__ALL__" for lbl in self._labels):
            all_labels = [m for m in type(self._labels[0]) if m.value != "__ALL__"]
        else:
            all_labels = self._labels
        tc_pairs = [[self._TC_HEAD, lbl.value] for lbl in all_labels]
        spec: dict = {
            "name": self.__class__.__name__,
            "condition": str(self._condition),
            "action": str(self._action),
            "level": 2,
            "types": {"regex": False, "ner": False, "tc": True},
            "required": {"regex": [], "ner": [], "tc": tc_pairs},
            "allowlist": list(self._allowlist),
            "bundles": [],
            "k": 0,
        }
        if self._threshold is not None:
            spec["threshold"] = self._threshold
        return spec
