"""
Completion command for MiniMax Code CLI.

Provides code completion functionality using AI models with rich output formatting
through the presenter system.
"""

import logging
from typing import Any, Optional
from pathlib import Path

from .base import BaseCommand
from ..exceptions import ValidationError


class CompletionCommand(BaseCommand):
    """Command for AI-powered code completion."""
    
    def __init__(self, client, config, presenter):
        """Initialize the completion command.
        
        Args:
            client: HuggingFace inference client
            config: Application configuration
            presenter: Presenter instance for output handling
        """
        super().__init__(client, config, presenter)
        self.logger = logging.getLogger(__name__)
    
    def execute(self, args: Any) -> bool:
        """Execute the completion command.
        
        Args:
            args: Parsed command line arguments containing:
                - prompt: The completion prompt/context
                - file: Optional file to complete
                - line: Optional line number for context
                - max_tokens: Maximum tokens to generate
                - temperature: Sampling temperature
                
        Returns:
            True if completion was successful, False otherwise
        """
        try:
            # Validate arguments
            if not hasattr(args, 'prompt') or not args.prompt:
                if not hasattr(args, 'file') or not args.file:
                    self.presenter.show_error("Either prompt or file must be provided for completion")
                    return False
            
            # Show operation start notification
            self.presenter.show_notification("Starting code completion...", level='info')
            
            # Prepare completion context
            context = self._prepare_context(args)
            if not context:
                return False
            
            # Generate completion
            completion_result = self.complete(context, args)
            if not completion_result:
                return False
            
            # Display results using presenter
            self._display_completion_result(completion_result, args)
            
            self.presenter.show_notification("Code completion completed successfully", level='success')
            return True
            
        except ValidationError as e:
            self.presenter.show_error(f"Validation error: {str(e)}")
            return False
        except Exception as e:
            self.logger.error(f"Error in completion command: {e}")
            self.presenter.show_error(f"Completion failed: {str(e)}")
            return False
    
    def complete(self, context: str, args: Any) -> Optional[str]:
        """Generate code completion using AI.
        
        Args:
            context: The context/prompt for completion
            args: Command arguments with completion parameters
            
        Returns:
            Generated completion text, or None if failed
        """
        try:
            # Prepare completion prompt
            prompt = self._build_completion_prompt(context, args)
            
            # Show progress for completion generation
            with self.presenter.show_progress("Generating completion", total=None) as progress:
                progress.update(description="Sending request to AI model...")
                
                # Generate completion with streaming if supported
                if hasattr(args, 'stream') and args.stream:
                    completion = self.ask_ai(
                        prompt=prompt,
                        use_cache=getattr(args, 'use_cache', True),
                        stream=True
                    )
                else:
                    completion = self.ask_ai(
                        prompt=prompt,
                        use_cache=getattr(args, 'use_cache', True),
                        stream=False
                    )
                
                progress.update(description="Processing completion...")
            
            if not completion:
                self.presenter.show_error("Failed to generate completion")
                return None
            
            return completion.strip()
            
        except Exception as e:
            self.logger.error(f"Error generating completion: {e}")
            self.presenter.show_error(f"Completion generation failed: {str(e)}")
            return None
    
    def _prepare_context(self, args: Any) -> Optional[str]:
        """Prepare the context for completion.
        
        Args:
            args: Command arguments
            
        Returns:
            Prepared context string, or None if failed
        """
        try:
            context_parts = []
            
            # Add file context if provided
            if hasattr(args, 'file') and args.file:
                file_path = Path(args.file)
                if not file_path.exists():
                    self.presenter.show_error(f"File not found: {args.file}")
                    return None
                
                # Read file content
                file_content = self.read_file(str(file_path))
                if not file_content:
                    return None
                
                # Detect language for better completion
                language = self.detect_language(str(file_path))
                
                # Add file context
                context_parts.append(f"File: {args.file}")
                context_parts.append(f"Language: {language}")
                
                # If line number specified, focus on that area
                if hasattr(args, 'line') and args.line:
                    lines = file_content.split('\n')
                    line_num = int(args.line) - 1  # Convert to 0-based
                    
                    # Get context around the line
                    start_line = max(0, line_num - 10)
                    end_line = min(len(lines), line_num + 10)
                    context_lines = lines[start_line:end_line]
                    
                    context_parts.append("Context around line {}:".format(args.line))
                    context_parts.append('\n'.join(context_lines))
                    
                    # Mark the specific line for completion
                    if line_num < len(lines):
                        context_parts.append(f"Complete this line: {lines[line_num]}")
                else:
                    # Use entire file as context
                    context_parts.append("File content:")
                    context_parts.append(file_content)
            
            # Add explicit prompt if provided
            if hasattr(args, 'prompt') and args.prompt:
                context_parts.append("Completion request:")
                context_parts.append(args.prompt)
            
            return '\n\n'.join(context_parts)
            
        except Exception as e:
            self.logger.error(f"Error preparing context: {e}")
            self.presenter.show_error(f"Failed to prepare completion context: {str(e)}")
            return None
    
    def _build_completion_prompt(self, context: str, args: Any) -> str:
        """Build the AI prompt for completion.
        
        Args:
            context: The prepared context
            args: Command arguments
            
        Returns:
            Formatted prompt for the AI model
        """
        prompt_parts = [
            "You are an expert code completion assistant. Please provide intelligent code completion based on the given context.",
            "",
            "Instructions:",
            "- Analyze the context and provide the most likely completion",
            "- Maintain consistent coding style and patterns",
            "- Follow language-specific best practices",
            "- Provide only the completion, not explanations unless requested",
            "- Ensure the completion is syntactically correct",
            "",
            "Context:",
            context
        ]
        
        # Add specific completion instructions based on arguments
        if hasattr(args, 'type') and args.type:
            if args.type == 'function':
                prompt_parts.append("\nPlease complete the function implementation.")
            elif args.type == 'class':
                prompt_parts.append("\nPlease complete the class definition.")
            elif args.type == 'docstring':
                prompt_parts.append("\nPlease complete the docstring documentation.")
            elif args.type == 'comment':
                prompt_parts.append("\nPlease complete the comment.")
        
        # Add length constraints
        if hasattr(args, 'max_tokens') and args.max_tokens:
            prompt_parts.append(f"\nLimit the completion to approximately {args.max_tokens} tokens.")
        
        prompt_parts.append("\nCompletion:")
        
        return '\n'.join(prompt_parts)
    
    def _display_completion_result(self, completion: str, args: Any) -> None:
        """Display the completion result using appropriate presenter methods.
        
        Args:
            completion: The generated completion
            args: Command arguments
        """
        try:
            # Determine if completion contains code
            is_code = self._is_code_completion(completion, args)
            
            # Show header
            self.presenter.show_header("Code Completion Result")
            
            if is_code:
                # Display as code with syntax highlighting
                language = None
                if hasattr(args, 'file') and args.file:
                    language = self.detect_language(args.file)
                elif hasattr(args, 'language') and args.language:
                    language = args.language
                
                self.presenter.show_code(
                    completion,
                    language=language,
                    title="Generated Code",
                    line_numbers=True
                )
            else:
                # Check if it's markdown-formatted
                if self._is_markdown_content(completion):
                    self.presenter.show_markdown(completion)
                else:
                    # Display as plain text
                    self.presenter.show_text(completion)
            
            # Show completion metadata if requested
            if hasattr(args, 'show_metadata') and args.show_metadata:
                metadata = [
                    {
                        "Property": "Length",
                        "Value": f"{len(completion)} characters"
                    },
                    {
                        "Property": "Lines",
                        "Value": str(len(completion.split('\n')))
                    },
                    {
                        "Property": "Type",
                        "Value": "Code" if is_code else "Text"
                    }
                ]
                
                if hasattr(args, 'file') and args.file:
                    metadata.append({
                        "Property": "Source File",
                        "Value": args.file
                    })
                
                self.presenter.show_table(
                    metadata,
                    title="Completion Metadata"
                )
            
        except Exception as e:
            self.logger.error(f"Error displaying completion result: {e}")
            self.presenter.show_error(f"Failed to display completion: {str(e)}")
    
    def _is_code_completion(self, completion: str, args: Any) -> bool:
        """Determine if the completion is code.
        
        Args:
            completion: The completion text
            args: Command arguments
            
        Returns:
            True if completion appears to be code
        """
        # Check if file extension suggests code
        if hasattr(args, 'file') and args.file:
            file_path = Path(args.file)
            code_extensions = {
                '.py', '.js', '.ts', '.java', '.cpp', '.c', '.cs', '.go', 
                '.rs', '.php', '.rb', '.swift', '.kt', '.scala', '.sh'
            }
            if file_path.suffix.lower() in code_extensions:
                return True
        
        # Check completion content for code patterns
        code_indicators = [
            'def ', 'class ', 'function ', 'var ', 'let ', 'const ',
            'import ', 'from ', 'include ', '#include', 'using ',
            '{', '}', '()', '=>', '->', '::',
            'if (', 'for (', 'while (', 'try {', 'catch ('
        ]
        
        completion_lower = completion.lower()
        return any(indicator in completion_lower for indicator in code_indicators)
    
    def _is_markdown_content(self, content: str) -> bool:
        """Check if content appears to be markdown.
        
        Args:
            content: The content to check
            
        Returns:
            True if content appears to be markdown
        """
        markdown_indicators = [
            '# ', '## ', '### ', '#### ',  # Headers
            '**', '__',  # Bold
            '*', '_',    # Italic
            '```',       # Code blocks
            '- ', '* ',  # Lists
            '[', ']()',  # Links
            '|',         # Tables
        ]
        
        return any(indicator in content for indicator in markdown_indicators)


class CompletionCommands:
    """Container for completion-related commands."""
    
    def __init__(self, client, config, presenter):
        """Initialize completion commands.
        
        Args:
            client: HuggingFace inference client
            config: Application configuration
            presenter: Presenter instance for output handling
        """
        self.completion = CompletionCommand(client, config, presenter)
    
    def complete(self, args: Any) -> bool:
        """Execute completion command.
        
        Args:
            args: Parsed command line arguments
            
        Returns:
            True if successful, False otherwise
        """
        return self.completion.execute(args)