"""
MLL Intake Semantic Classifier
4-stage semantic classification pipeline
"""

import re
from typing import Dict, Any, List, Optional, Tuple
from pathlib import Path
from loguru import logger

import sys
sys.path.insert(0, str(Path(__file__).parent.parent))
from config import MLL_SITES, CAPABILITY_CENTERS, COMPONENT_TYPES, NETWORK_PRIORITIES, INTENT_PATTERNS
from models.schemas import ClassificationResult, RequestType, CapabilityCenter, Intent
from utils.embeddings import search_similar


class SemanticClassifier:
    """4-Stage Semantic Classification Pipeline"""
    
    def __init__(self):
        self._initialized = False
    
    def initialize(self) -> bool:
        """Initialize the classifier"""
        self._initialized = True
        return True
    
    def classify(self, user_input: str, context: Optional[Dict[str, Any]] = None) -> ClassificationResult:
        """Run full classification pipeline"""
        context = context or {}
        
        # Stage 1: Named Entity Recognition
        entities = self._stage1_ner(user_input)
        
        # Stage 2: Ontology Reasoning
        request_type, capability_center, routing = self._stage2_ontology(user_input, entities)
        
        # Stage 3: Embedding Similarity
        similar_requests = self._stage3_similarity(user_input)
        
        # Stage 4: Context Enrichment (simplified)
        
        # Determine intent
        intent = self._determine_intent(user_input, entities)
        
        # Calculate confidence
        confidence = self._calculate_confidence(entities, request_type, similar_requests, intent)
        
        # Check requirements
        requires_network = self._check_network_requirement(user_input, entities)
        requires_nexus = capability_center in [CapabilityCenter.AGILE_DEMAND, CapabilityCenter.APPROVED_PROJECT]
        
        return ClassificationResult(
            request_type=request_type,
            capability_center=capability_center,
            intent=intent,
            confidence=confidence,
            entities=entities,
            similar_requests=similar_requests,
            routing_system=routing,
            requires_network=requires_network,
            requires_nexus_id=requires_nexus
        )
    
    def _stage1_ner(self, text: str) -> Dict[str, Any]:
        """Stage 1: Named Entity Recognition"""
        entities = {
            'sites': [],
            'ritm_numbers': [],
            'jira_keys': [],
            'components': [],
            'applications': [],
            'priorities': []
        }
        
        text_upper = text.upper()
        
        # Extract RITM numbers
        entities['ritm_numbers'] = re.findall(r'RITM\d{12,15}', text_upper)
        
        # Extract Jira keys
        entities['jira_keys'] = re.findall(r'ABFZ-\d+', text_upper)
        
        # Extract sites
        for site_id, site_info in MLL_SITES.items():
            if site_info['name'].upper() in text_upper:
                entities['sites'].append({
                    'site_id': site_id,
                    'name': site_info['name'],
                    'country': site_info['country']
                })
        
        # Extract components
        for component in COMPONENT_TYPES:
            if component.upper() in text_upper:
                entities['components'].append(component)
        
        # Extract priorities
        for priority in NETWORK_PRIORITIES.keys():
            if priority in text_upper:
                entities['priorities'].append(priority)
        
        # Extract TS ENGAGE reference
        if 'TS ENGAGE' in text_upper or 'TSENGAGE' in text_upper:
            entities['applications'].append('TS ENGAGE-PROD')
        
        return entities
    
    def _stage2_ontology(self, text: str, entities: Dict[str, Any]) -> Tuple[RequestType, CapabilityCenter, str]:
        """Stage 2: Ontology Reasoning"""
        text_lower = text.lower()
        text_upper = text.upper()
        
        request_type = RequestType.UNKNOWN
        capability_center = CapabilityCenter.UNKNOWN
        routing = "IRIS"
        
        # Network Request Detection
        network_keywords = ['network', 'firewall', 'switch', 'lan', 'wan', 'vlan', 'cable drop', 'connectivity']
        if any(kw in text_lower for kw in network_keywords):
            request_type = RequestType.NETWORK
        
        # Incident Detection
        incident_keywords = ['not working', 'broken', 'down', 'error', 'issue', 'problem', 'stopped', 'failed']
        if any(kw in text_lower for kw in incident_keywords):
            request_type = RequestType.INCIDENT
        
        # Access Request Detection
        access_keywords = ['access', 'permission', 'login', 'account', 'credentials']
        if any(kw in text_lower for kw in access_keywords):
            request_type = RequestType.ACCESS
            if 'TS ENGAGE' in text_upper:
                routing = "TS_ENGAGE"
        
        # Status Query Detection
        if entities.get('ritm_numbers') or entities.get('jira_keys'):
            status_keywords = ['status', 'update', 'where is', 'progress', 'check']
            if any(kw in text_lower for kw in status_keywords):
                request_type = RequestType.STATUS
        
        # Default to Intake
        if request_type == RequestType.UNKNOWN:
            new_request_keywords = ['new', 'request', 'need', 'want', 'implement', 'install', 'create']
            if any(kw in text_lower for kw in new_request_keywords):
                request_type = RequestType.INTAKE
        
        # Determine capability center
        if 'agile' in text_lower:
            capability_center = CapabilityCenter.AGILE_DEMAND
        elif 'project' in text_lower and 'nexus' in text_lower:
            capability_center = CapabilityCenter.APPROVED_PROJECT
        elif 'estimate' in text_lower:
            capability_center = CapabilityCenter.ESTIMATE_DEMAND
        elif 'ts internal' in text_lower:
            capability_center = CapabilityCenter.TS_INTERNAL
        
        return request_type, capability_center, routing
    
    def _stage3_similarity(self, text: str) -> List[Dict[str, Any]]:
        """Stage 3: Embedding Similarity"""
        try:
            return search_similar(text, top_k=5)
        except Exception as e:
            logger.warning(f"Similarity search failed: {e}")
            return []
    
    def _determine_intent(self, text: str, entities: Dict[str, Any]) -> Intent:
        """Determine user intent"""
        text_lower = text.lower()
        
        # Check for status query first
        if entities.get('ritm_numbers') or entities.get('jira_keys'):
            for pattern in INTENT_PATTERNS.get('check_status', []):
                if pattern in text_lower:
                    return Intent.CHECK_STATUS
        
        # Check other intents
        for intent_name, patterns in INTENT_PATTERNS.items():
            for pattern in patterns:
                if pattern in text_lower:
                    return Intent(intent_name)
        
        return Intent.CREATE_REQUEST
    
    def _check_network_requirement(self, text: str, entities: Dict[str, Any]) -> bool:
        """Check if request requires network team"""
        text_lower = text.lower()
        network_indicators = ['network', 'firewall', 'switch', 'cable drop', 'lan', 'wan', 'vlan']
        
        if any(ind in text_lower for ind in network_indicators):
            return True
        
        if any(comp.lower() in network_indicators for comp in entities.get('components', [])):
            return True
        
        return False
    
    def _calculate_confidence(self, entities, request_type, similar_requests, intent) -> float:
        """Calculate classification confidence"""
        confidence = 0.5
        
        if entities.get('sites'):
            confidence += 0.1
        if entities.get('ritm_numbers') or entities.get('jira_keys'):
            confidence += 0.15
        if entities.get('components'):
            confidence += 0.1
        if request_type != RequestType.UNKNOWN:
            confidence += 0.1
        if similar_requests:
            confidence += min(0.2, similar_requests[0].get('similarity_score', 0) * 0.2)
        if intent != Intent.UNKNOWN:
            confidence += 0.1
        
        return min(1.0, confidence)


# Global instance
classifier = SemanticClassifier()


def initialize_classifier() -> bool:
    """Initialize the global classifier"""
    return classifier.initialize()


def classify_request(user_input: str, context: Optional[Dict[str, Any]] = None) -> ClassificationResult:
    """Classify a user request"""
    if not classifier._initialized:
        classifier.initialize()
    return classifier.classify(user_input, context)
