"""
Gremlin Chat intent classification (Python port of intent_classifier.gs).

This module provides the same intent classification logic as the Apps Script
version, enabling fast local testing without the Apps Script Execution API.
"""

from __future__ import annotations

import re
from typing import Any


class GremlinIntents:
    """Intent constants matching GREMLIN_INTENTS in intent_classifier.gs."""

    IP_BLOCKED = "ip_blocked"
    STATUS = "status"
    PRODUCT_INFO = "product_info"
    SHEET_OP = "sheet_op"
    NOISE = "noise"
    NOISE_OVERRIDE = "noise_override"


# Regex patterns matching intent_classifier.gs
OVERRIDE_PATTERNS = re.compile(
    r"\b(just answer|off.?topic|humor me|quick question)\b", re.IGNORECASE
)

IP_BLOCKED_REGEX = re.compile(
    r"\b(source code|python code|python|prompt|system|heuristic|model|weights|algorithm|implementation)\b",
    re.IGNORECASE,
)

STATUS_REGEX = re.compile(
    r"\b(did you|did u|did you complete|did you finish|did you run|did you do|done|finished|status|work|run)\b",
    re.IGNORECASE,
)

PRODUCT_INFO_REGEX = re.compile(
    r"\b(full list|list all|list of|what transforms|transforms do you offer|what can you do|capabilities|features)\b",
    re.IGNORECASE,
)

SHEET_VERB_REGEX = re.compile(
    r"\b(clean|match|dedupe|de[- ]?dupe|normalize|transform|apply|enrich|audit|fix|remove|split|merge|convert|format|standardize|trim|map|parse)\b",
    re.IGNORECASE,
)

SHEET_REF_REGEX = re.compile(
    r"\b(column|col|row|cell|range|tab|sheet)\b|\b[A-Z]{1,2}\d+(?::[A-Z]{1,2}\d+)?\b",
    re.IGNORECASE,
)


def classify_intent(
    message: str,
    context: dict[str, Any] | None = None,
    state: dict[str, Any] | None = None,
) -> dict[str, Any]:
    """
    Classify a Gremlin chat message into an intent category.

    This function mirrors classifyGremlinIntent_() in intent_classifier.gs.

    Args:
        message: The user message to classify
        context: Optional context dict (currently unused but reserved)
        state: Optional state dict with lastIntent for override detection

    Returns:
        Dict with 'intent' key and optional 'allowOnce' for overrides
    """
    text = (message or "").strip()
    last_intent = (state or {}).get("lastIntent")

    if not text:
        return {"intent": GremlinIntents.NOISE}

    if IP_BLOCKED_REGEX.search(text):
        return {"intent": GremlinIntents.IP_BLOCKED}

    if last_intent == GremlinIntents.NOISE and OVERRIDE_PATTERNS.search(text):
        return {"intent": GremlinIntents.NOISE_OVERRIDE, "allowOnce": True}

    if STATUS_REGEX.search(text):
        return {"intent": GremlinIntents.STATUS}

    if PRODUCT_INFO_REGEX.search(text):
        return {"intent": GremlinIntents.PRODUCT_INFO}

    has_sheet_verb = bool(SHEET_VERB_REGEX.search(text))
    has_sheet_ref = bool(SHEET_REF_REGEX.search(text))

    if has_sheet_verb or has_sheet_ref:
        return {"intent": GremlinIntents.SHEET_OP}

    return {"intent": GremlinIntents.NOISE}
