"""Contextual suggestion system for better user experience."""

import json
from pathlib import Path
from typing import Dict, List, Optional, Set, Tuple
from rich.console import Console

from ..core.project import ProjectManager
from ..core.exceptions import ProjectNotFoundError


class ContextualSuggestionProvider:
    """Provides context-aware suggestions based on project state and user workflow."""
    
    def __init__(self, project_root: Optional[Path] = None):
        """Initialize the suggestion provider.
        
        Args:
            project_root: Root directory of the project (defaults to current directory)
        """
        self.project_root = project_root or Path.cwd()
        self.console = Console(stderr=True)
        
    def get_project_state(self) -> Dict[str, bool]:
        """Analyze the current project state.
        
        Returns:
            Dictionary with boolean flags indicating project state
        """
        state = {
            'is_initialized': False,
            'has_index': False,
            'has_config': False,
            'has_recent_changes': False,
            'is_git_repo': False,
            'has_mcp_config': False
        }
        
        try:
            # Check if project is initialized
            config_dir = self.project_root / '.mcp-vector-search'
            state['is_initialized'] = config_dir.exists()
            
            if state['is_initialized']:
                # Check for config
                config_file = config_dir / 'config.json'
                state['has_config'] = config_file.exists()
                
                # Check for index
                index_dir = config_dir / 'chroma_db'
                state['has_index'] = index_dir.exists() and any(index_dir.iterdir())
                
            # Check if it's a git repo
            git_dir = self.project_root / '.git'
            state['is_git_repo'] = git_dir.exists()
            
            # Check for MCP configuration (Claude Desktop config)
            home = Path.home()
            claude_config = home / 'Library' / 'Application Support' / 'Claude' / 'claude_desktop_config.json'
            if claude_config.exists():
                try:
                    with open(claude_config) as f:
                        config_data = json.load(f)
                        mcp_servers = config_data.get('mcpServers', {})
                        state['has_mcp_config'] = 'mcp-vector-search' in mcp_servers
                except (json.JSONDecodeError, IOError):
                    pass
            
            # TODO: Check for recent file changes (would need file system monitoring)
            # For now, we'll assume false
            state['has_recent_changes'] = False
            
        except Exception:
            # If we can't determine state, provide conservative defaults
            pass
            
        return state
    
    def get_workflow_suggestions(self, failed_command: str) -> List[Dict[str, str]]:
        """Get workflow-based suggestions for a failed command.
        
        Args:
            failed_command: The command that failed
            
        Returns:
            List of suggestion dictionaries with 'command', 'reason', and 'priority'
        """
        suggestions = []
        state = self.get_project_state()
        
        # High priority suggestions based on project state
        if not state['is_initialized']:
            suggestions.append({
                'command': 'init',
                'reason': 'Project is not initialized for vector search',
                'priority': 'high',
                'description': 'Set up the project configuration and create necessary directories'
            })
        elif not state['has_index']:
            suggestions.append({
                'command': 'index',
                'reason': 'No search index found - create one to enable searching',
                'priority': 'high',
                'description': 'Build the vector index for your codebase'
            })
        
        # Context-specific suggestions based on the failed command
        if failed_command.lower() in ['search', 'find', 'query', 's', 'f']:
            if not state['has_index']:
                suggestions.append({
                    'command': 'index',
                    'reason': 'Cannot search without an index',
                    'priority': 'high',
                    'description': 'Build the search index first'
                })
            else:
                suggestions.extend([
                    {
                        'command': 'search',
                        'reason': 'Correct command for semantic code search',
                        'priority': 'high',
                        'description': 'Search your codebase semantically'
                    },
                    {
                        'command': 'interactive',
                        'reason': 'Try interactive search for better experience',
                        'priority': 'medium',
                        'description': 'Start an interactive search session'
                    }
                ])
        
        elif failed_command.lower() in ['index', 'build', 'scan', 'i', 'b']:
            suggestions.append({
                'command': 'index',
                'reason': 'Correct command for building search index',
                'priority': 'high',
                'description': 'Index your codebase for semantic search'
            })
            
        elif failed_command.lower() in ['status', 'info', 'stat', 'st']:
            suggestions.append({
                'command': 'status',
                'reason': 'Show project status and statistics',
                'priority': 'high',
                'description': 'Display current project information'
            })
            
        elif failed_command.lower() in ['config', 'configure', 'settings', 'c']:
            suggestions.append({
                'command': 'config',
                'reason': 'Manage project configuration',
                'priority': 'high',
                'description': 'View or modify project settings'
            })
        
        # MCP-related suggestions
        if not state['has_mcp_config'] and failed_command.lower() in ['mcp', 'claude', 'server']:
            suggestions.append({
                'command': 'init-mcp',
                'reason': 'Set up Claude Code MCP integration',
                'priority': 'medium',
                'description': 'Configure MCP server for Claude Code integration'
            })
        
        # Remove duplicates while preserving order
        seen = set()
        unique_suggestions = []
        for suggestion in suggestions:
            key = suggestion['command']
            if key not in seen:
                seen.add(key)
                unique_suggestions.append(suggestion)
        
        return unique_suggestions
    
    def get_next_steps(self) -> List[Dict[str, str]]:
        """Get suggested next steps based on current project state.
        
        Returns:
            List of suggested next step dictionaries
        """
        state = self.get_project_state()
        next_steps = []
        
        if not state['is_initialized']:
            next_steps.append({
                'command': 'init',
                'description': 'Initialize the project for semantic search',
                'priority': 'high'
            })
        elif not state['has_index']:
            next_steps.append({
                'command': 'index',
                'description': 'Build the search index for your codebase',
                'priority': 'high'
            })
        else:
            # Project is ready for use
            next_steps.extend([
                {
                    'command': 'search "your query here"',
                    'description': 'Search your codebase semantically',
                    'priority': 'high'
                },
                {
                    'command': 'status',
                    'description': 'Check project statistics and index health',
                    'priority': 'medium'
                }
            ])
            
            if state['has_recent_changes']:
                next_steps.insert(0, {
                    'command': 'index --force',
                    'description': 'Update the index with recent changes',
                    'priority': 'high'
                })
        
        if not state['has_mcp_config'] and state['is_initialized']:
            next_steps.append({
                'command': 'init-mcp',
                'description': 'Set up Claude Code integration',
                'priority': 'low'
            })
        
        return next_steps
    
    def show_contextual_help(self, failed_command: Optional[str] = None) -> None:
        """Show contextual help and suggestions.
        
        Args:
            failed_command: The command that failed (if any)
        """
        if failed_command:
            self.console.print(f"\n[yellow]Command '{failed_command}' not recognized.[/yellow]")
            
            suggestions = self.get_workflow_suggestions(failed_command)
            if suggestions:
                self.console.print("\n[bold]Based on your project state, you might want to try:[/bold]")
                
                for i, suggestion in enumerate(suggestions[:3], 1):  # Show top 3
                    priority_color = {
                        'high': 'red',
                        'medium': 'yellow', 
                        'low': 'dim'
                    }.get(suggestion['priority'], 'white')
                    
                    self.console.print(
                        f"  [{priority_color}]{i}.[/{priority_color}] "
                        f"[bold cyan]mcp-vector-search {suggestion['command']}[/bold cyan]"
                    )
                    self.console.print(f"     {suggestion['description']}")
                    if suggestion.get('reason'):
                        self.console.print(f"     [dim]({suggestion['reason']})[/dim]")
        else:
            # Show general next steps
            next_steps = self.get_next_steps()
            if next_steps:
                self.console.print("\n[bold]Suggested next steps:[/bold]")
                
                for i, step in enumerate(next_steps[:3], 1):
                    priority_color = {
                        'high': 'green',
                        'medium': 'yellow',
                        'low': 'dim'
                    }.get(step['priority'], 'white')
                    
                    self.console.print(
                        f"  [{priority_color}]{i}.[/{priority_color}] "
                        f"[bold cyan]mcp-vector-search {step['command']}[/bold cyan]"
                    )
                    self.console.print(f"     {step['description']}")
    
    def get_command_completion_suggestions(self, partial_command: str) -> List[str]:
        """Get command completion suggestions for a partial command.
        
        Args:
            partial_command: Partial command string
            
        Returns:
            List of possible command completions
        """
        all_commands = [
            'search', 'index', 'status', 'config', 'init', 'mcp', 
            'doctor', 'version', 'watch', 'auto-index', 'history',
            'interactive', 'demo', 'install', 'reset', 'health'
        ]
        
        # Add common aliases and shortcuts
        all_commands.extend(['s', 'i', 'st', 'c', 'f', 'find'])
        
        partial_lower = partial_command.lower()
        matches = [
            cmd for cmd in all_commands 
            if cmd.startswith(partial_lower)
        ]
        
        return sorted(matches)


def get_contextual_suggestions(project_root: Optional[Path] = None, 
                             failed_command: Optional[str] = None) -> None:
    """Get and display contextual suggestions.
    
    Args:
        project_root: Root directory of the project
        failed_command: The command that failed
    """
    provider = ContextualSuggestionProvider(project_root)
    provider.show_contextual_help(failed_command)


def suggest_workflow_commands(project_root: Optional[Path] = None) -> List[str]:
    """Get workflow command suggestions for the current project state.
    
    Args:
        project_root: Root directory of the project
        
    Returns:
        List of suggested commands in priority order
    """
    provider = ContextualSuggestionProvider(project_root)
    next_steps = provider.get_next_steps()
    
    return [step['command'] for step in next_steps]