"""Intelligence Manager for coordinating intelligent components."""
import json
import os
from datetime import datetime
from pathlib import Path
from typing import Dict, List, Optional, Any, Union
import logging
import asyncio
from dataclasses import dataclass, asdict

from .context_manager import ContextManager
from .goal_manager import GoalManager
from .resource_manager import ResourceManager
from .learning_manager import LearningManager
from .clarification_manager import ClarificationManager

logger = logging.getLogger(__name__)

@dataclass
class IntelligenceConfig:
    """Configuration for the Intelligence Manager."""
    workspace_root: str
    cache_dir: str = '.cursor/cache'
    learning_db_path: str = '.cursor/learning.json'
    context_db_path: str = '.cursor/context_db.json'
    enable_auto_learning: bool = True
    enable_goal_tracking: bool = True
    enable_resource_caching: bool = True
    enable_clarification: bool = True

class IntelligenceManager:
    """Coordinates intelligent components for enhanced capabilities."""
    
    def __init__(self, config: IntelligenceConfig):
        """Initialize the Intelligence Manager."""
        self.config = config
        self.workspace_root = Path(config.workspace_root)
        
        # Initialize component managers
        self.context_manager = ContextManager(config.workspace_root)
        self.goal_manager = GoalManager(self.context_manager)
        self.resource_manager = ResourceManager(
            config.workspace_root, 
            config.cache_dir
        )
        self.learning_manager = LearningManager(
            config.workspace_root,
            config.learning_db_path
        )
        self.clarification_manager = ClarificationManager(
            self.context_manager,
            self,
            self.goal_manager,
            self.resource_manager
        )
        
        # Set up event loop for async operations
        self.loop = asyncio.get_event_loop()
        
        logger.info("Intelligence Manager initialized")

    async def analyze_request(self, request: str) -> Dict[str, Any]:
        """Analyze a user request using all available intelligence."""
        analysis = {
            'timestamp': datetime.now().isoformat(),
            'request': request,
            'context': {},
            'relevant_goals': [],
            'learned_patterns': [],
            'resources': [],
            'clarification_needed': False,
            'clarification_questions': []
        }
        
        # First, check if we need clarification
        if self.config.enable_clarification:
            clarification_analysis = self.clarification_manager.analyze_request(request)
            if clarification_analysis['required_clarifications']:
                analysis['clarification_needed'] = True
                analysis['clarification_questions'] = [
                    asdict(q) for q in clarification_analysis['suggested_questions']
                ]
                return analysis  # Return early if clarification is needed
        
        # Get current project context
        context = self.context_manager.get_project_context()
        analysis['context'] = context  # Context is already a dict
        
        # Find relevant goals
        active_goals = self.goal_manager.get_active_goals()
        analysis['relevant_goals'] = [
            asdict(goal) for goal in active_goals
            if any(keyword in request.lower() 
                  for keyword in goal.description.lower().split())
        ]
        
        # Check learned patterns
        patterns = self.learning_manager.find_similar_cases(request)
        analysis['learned_patterns'] = patterns
        
        # Fetch relevant resources
        resources = []
        if self.config.enable_resource_caching:
            # Extract keywords for resource search
            keywords = self._extract_keywords(request)
            for keyword in keywords:
                resources.extend(
                    self.resource_manager.get_resources_by_tag(keyword)
                )
        analysis['resources'] = [asdict(r) for r in resources]
        
        return analysis

    async def execute_action(self, action: str, 
                           params: Dict[str, Any]) -> Dict[str, Any]:
        """Execute an action with intelligence augmentation."""
        result = {
            'timestamp': datetime.now().isoformat(),
            'action': action,
            'params': params,
            'success': False,
            'output': None,
            'error': None,
            'clarification_needed': False,
            'clarification_questions': []
        }
        
        try:
            # Check if we need clarification before execution
            if self.config.enable_clarification:
                clarification_analysis = self.clarification_manager.analyze_request(
                    f"{action} with params {json.dumps(params)}"
                )
                if clarification_analysis['required_clarifications']:
                    result['clarification_needed'] = True
                    result['clarification_questions'] = [
                        asdict(q) for q in clarification_analysis['suggested_questions']
                    ]
                    return result  # Return early if clarification is needed
            
            # Record action context
            self.context_manager.add_insight(
                f"Executing action: {action}",
                'action_execution',
                'intelligence_manager'
            )
            
            # Check for learned patterns
            patterns = self.learning_manager.find_similar_cases(action)
            if patterns:
                logger.info(f"Found {len(patterns)} relevant patterns")
                # Apply learned optimizations
                params = self._apply_learned_optimizations(params, patterns)
            
            # Execute the action
            output = await self._execute_action_impl(action, params)
            result['success'] = True
            result['output'] = output
            
            # Record success for learning
            if self.config.enable_auto_learning:
                self.learning_manager.record_success(
                    action,
                    params,
                    output
                )
            
            # Update goals if relevant
            if self.config.enable_goal_tracking:
                self._update_goals_after_action(action, output)
            
        except Exception as e:
            logger.error(f"Error executing action {action}: {e}")
            result['error'] = str(e)
            
            # Record error for learning
            if self.config.enable_auto_learning:
                self.learning_manager.record_error(
                    action,
                    params,
                    str(e)
                )
        
        return result

    def record_feedback(self, action: str, success: bool, 
                       feedback: str) -> None:
        """Record user feedback for learning."""
        if self.config.enable_auto_learning:
            if success:
                self.learning_manager.record_success(
                    action,
                    {},  # No params for feedback
                    feedback
                )
            else:
                self.learning_manager.record_correction(
                    action,
                    {},  # No params for feedback
                    feedback
                )
            
        # Add insight about feedback
        self.context_manager.add_insight(
            f"User feedback for {action}: {feedback}",
            'user_feedback',
            'intelligence_manager'
        )

    def get_intelligence_status(self) -> Dict[str, Any]:
        """Get the current status of all intelligence components."""
        return {
            'timestamp': datetime.now().isoformat(),
            'project_context': self.context_manager.get_project_context(),  # Already a dict
            'active_goals': [
                asdict(g) for g in self.goal_manager.get_active_goals()
            ],
            'learning_stats': self.learning_manager.get_statistics(),
            'cached_resources': len(self.resource_manager.cache_index),
            'pending_clarifications': len([
                q for q in self.clarification_manager.questions.values()
                if q.status == "pending"
            ])
        }

    def record_clarification(self, question_id: str, answer: str) -> None:
        """Record a clarification answer."""
        if self.config.enable_clarification:
            self.clarification_manager.record_answer(question_id, answer)
            
            # Add insight about clarification
            self.context_manager.add_insight(
                f"Received clarification for question {question_id}",
                'clarification',
                'intelligence_manager'
            )

    def _extract_keywords(self, text: str) -> List[str]:
        """Extract relevant keywords from text."""
        # Simple keyword extraction for now
        # Could be enhanced with NLP in the future
        words = text.lower().split()
        stopwords = {'the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at'}
        return [w for w in words if w not in stopwords and len(w) > 2]

    def _apply_learned_optimizations(self, params: Dict[str, Any],
                                   patterns: List[Dict[str, Any]]) -> Dict[str, Any]:
        """Apply learned optimizations to action parameters."""
        optimized = params.copy()
        
        for pattern in patterns:
            if pattern['success']:
                # Apply successful pattern modifications
                if 'optimizations' in pattern:
                    for key, value in pattern['optimizations'].items():
                        if key in optimized:
                            optimized[key] = value
                            
        return optimized

    async def _execute_action_impl(self, action: str,
                                 params: Dict[str, Any]) -> Any:
        """Implementation of action execution."""
        # This would be implemented based on available actions
        # For now, just log and return
        logger.info(f"Executing {action} with params {params}")
        return {'status': 'executed', 'action': action, 'params': params}

    def _update_goals_after_action(self, action: str, output: Any):
        """Update goals based on action output."""
        # This would be implemented based on goal metrics
        # For now, just log
        logger.info(f"Updating goals after {action}")
        
    def cleanup(self):
        """Cleanup resources and save state."""
        if self.config.enable_resource_caching:
            self.resource_manager.clear_expired_cache()
        self.learning_manager.save_database()
        logger.info("Intelligence Manager cleanup completed") 