"""
VSS Routing Agent
Classifies query intent: SQL vs VLM.
"""

import logging
import re
from typing import Optional, Tuple

from orchestration.state import VSSState, add_trace
from inference.llm_client import get_llm

logger = logging.getLogger(__name__)

# Rule-based patterns
SQL_PATTERNS = [
    r'\bhow many\b', r'\bcount\b', r'\btotal\b', r'\bsum\b',
    r'\baverage\b', r'\bmax\b', r'\bmin\b', r'\bpeak\b',
    r'\bmost common\b', r'\btrend\b', r'\bstatistics\b',
    r'\byesterday\b', r'\blast hour\b', r'\blast \d+ (hour|day|week)',
    r'\bbetween\b.*\band\b', r'\bsince\b', r'\bper (hour|day|category)\b',
]

VLM_PATTERNS = [
    r'\bshow me\b', r'\blook at\b', r'\bdescribe\b',
    r'\bwhat\'s happening\b', r'\bwhat is happening\b',
    r'\bin the (image|video|frame|scene)\b',
    r'\bcan you see\b', r'\bis there\b', r'\bidentify\b',
    r'\banalyze.*scene\b', r'\bvisual\b',
]

ROUTING_PROMPT = """Classify this video analytics query into SQL or VLM.

SQL: Counts, aggregations, statistics, time-based analytics
VLM: Visual analysis, scene description, image understanding

Query: {query}

Respond with exactly one word: SQL or VLM"""


class RoutingAgent:
    """Routes queries to SQL or VLM path."""
    
    def __init__(self):
        self._sql_patterns = [re.compile(p, re.I) for p in SQL_PATTERNS]
        self._vlm_patterns = [re.compile(p, re.I) for p in VLM_PATTERNS]
    
    async def classify(self, state: VSSState) -> VSSState:
        """Classify query intent."""
        query = state.get("user_query", "")
        
        if not query:
            state["intent"] = "unknown"
            state["intent_confidence"] = 0.0
            state["routing_reason"] = "Empty query"
            return state
        
        # Check for uploaded media → VLM
        if state.get("uploaded_media"):
            state["intent"] = "vlm"
            state["intent_confidence"] = 1.0
            state["routing_reason"] = "Media uploaded"
            add_trace(state, "Routing: Media detected → VLM")
            return state
        
        # Rule-based classification
        intent, confidence, reason = self._classify_rules(query)
        
        if confidence >= 0.8:
            state["intent"] = intent
            state["intent_confidence"] = confidence
            state["routing_reason"] = reason
            add_trace(state, f"Routing (rules): {intent} ({confidence:.2f})")
            return state
        
        # LLM classification for ambiguous cases
        intent, confidence, reason = await self._classify_llm(query)
        state["intent"] = intent
        state["intent_confidence"] = confidence
        state["routing_reason"] = reason
        add_trace(state, f"Routing (LLM): {intent} ({confidence:.2f})")
        
        return state
    
    def _classify_rules(self, query: str) -> Tuple[str, float, str]:
        """Rule-based classification using SQL and VLM pattern sets."""
        q = query.lower()

        sql_matches = sum(1 for p in self._sql_patterns if p.search(q))
        vlm_matches = sum(1 for p in self._vlm_patterns if p.search(q))
        
        #if sql_matches > 0 and vlm_matches == 0:
        #    return "sql", min(0.9, 0.6 + sql_matches * 0.1), f"SQL patterns: {sql_matches}"
        
        #if vlm_matches > 0 and sql_matches == 0:
        #    return "vlm", min(0.9, 0.6 + vlm_matches * 0.1), f"VLM patterns: {vlm_matches}"
        
        #if sql_matches > vlm_matches:
        #    return "sql", 0.5, f"Mixed: {sql_matches} SQL vs {vlm_matches} VLM"
        #elif vlm_matches > sql_matches:
        #    return "vlm", 0.5, f"Mixed: {vlm_matches} VLM vs {sql_matches} SQL"
        
        #return "unknown", 0.3, "No clear patterns"
        return "sql", min(0.9, 0.6 + sql_matches * 0.1), f"SQL patterns: {sql_matches}"
    
    async def _classify_llm(self, query: str) -> Tuple[str, float, str]:
        """LLM-based classification."""
        try:
            llm = get_llm()
            response = await llm.generate(
                ROUTING_PROMPT.format(query=query),
                max_tokens=10,
                temperature=0.1
            )
            
            resp = response.upper().strip()
            if "VLM" in resp:
                return "vlm", 0.8, "LLM classified VLM"
            elif "SQL" in resp:
                return "sql", 0.8, "LLM classified SQL"
            else:
                return "sql", 0.6, f"LLM unclear ({resp}), defaulting SQL"
                
        except Exception as e:
            logger.error(f"LLM classification failed: {e}")
            return "sql", 0.5, f"LLM error, defaulting SQL"


_routing_agent: Optional[RoutingAgent] = None


def _get_routing_agent() -> RoutingAgent:
    """Return the module-level RoutingAgent singleton (lazy init)."""
    global _routing_agent
    if _routing_agent is None:
        _routing_agent = RoutingAgent()
    return _routing_agent


async def classify_intent(state: VSSState) -> VSSState:
    """LangGraph node function."""
    return await _get_routing_agent().classify(state)