"""
User interface utilities for SuperClaude installation system
Cross-platform console UI with colors and progress indication
"""

import sys
import time
import shutil
from typing import List, Optional, Any, Dict, Union
from enum import Enum

# Try to import colorama for cross-platform color support
try:
    import colorama
    from colorama import Fore, Back, Style
    colorama.init(autoreset=True)
    COLORAMA_AVAILABLE = True
except ImportError:
    COLORAMA_AVAILABLE = False
    # Fallback color codes for Unix-like systems
    class MockFore:
        RED = '\033[91m' if sys.platform != 'win32' else ''
        GREEN = '\033[92m' if sys.platform != 'win32' else ''
        YELLOW = '\033[93m' if sys.platform != 'win32' else ''
        BLUE = '\033[94m' if sys.platform != 'win32' else ''
        MAGENTA = '\033[95m' if sys.platform != 'win32' else ''
        CYAN = '\033[96m' if sys.platform != 'win32' else ''
        WHITE = '\033[97m' if sys.platform != 'win32' else ''
    
    class MockStyle:
        RESET_ALL = '\033[0m' if sys.platform != 'win32' else ''
        BRIGHT = '\033[1m' if sys.platform != 'win32' else ''
    
    Fore = MockFore()
    Style = MockStyle()


class Colors:
    """Color constants for console output"""
    RED = Fore.RED
    GREEN = Fore.GREEN
    YELLOW = Fore.YELLOW
    BLUE = Fore.BLUE
    MAGENTA = Fore.MAGENTA
    CYAN = Fore.CYAN
    WHITE = Fore.WHITE
    RESET = Style.RESET_ALL
    BRIGHT = Style.BRIGHT


class ProgressBar:
    """Cross-platform progress bar with customizable display"""
    
    def __init__(self, total: int, width: int = 50, prefix: str = '', suffix: str = ''):
        """
        Initialize progress bar
        
        Args:
            total: Total number of items to process
            width: Width of progress bar in characters
            prefix: Text to display before progress bar
            suffix: Text to display after progress bar
        """
        self.total = total
        self.width = width
        self.prefix = prefix
        self.suffix = suffix
        self.current = 0
        self.start_time = time.time()
        
        # Get terminal width for responsive display
        try:
            self.terminal_width = shutil.get_terminal_size().columns
        except OSError:
            self.terminal_width = 80
    
    def update(self, current: int, message: str = '') -> None:
        """
        Update progress bar
        
        Args:
            current: Current progress value
            message: Optional message to display
        """
        self.current = current
        percent = min(100, (current / self.total) * 100) if self.total > 0 else 100
        
        # Calculate filled and empty portions
        filled_width = int(self.width * current / self.total) if self.total > 0 else self.width
        filled = '█' * filled_width
        empty = '░' * (self.width - filled_width)
        
        # Calculate elapsed time and ETA
        elapsed = time.time() - self.start_time
        if current > 0:
            eta = (elapsed / current) * (self.total - current)
            eta_str = f" ETA: {self._format_time(eta)}"
        else:
            eta_str = ""
        
        # Format progress line
        if message:
            status = f" {message}"
        else:
            status = ""
        
        progress_line = (
            f"\r{self.prefix}[{Colors.GREEN}{filled}{Colors.WHITE}{empty}{Colors.RESET}] "
            f"{percent:5.1f}%{status}{eta_str}"
        )
        
        # Truncate if too long for terminal
        max_length = self.terminal_width - 5
        if len(progress_line) > max_length:
            # Remove color codes for length calculation
            plain_line = progress_line.replace(Colors.GREEN, '').replace(Colors.WHITE, '').replace(Colors.RESET, '')
            if len(plain_line) > max_length:
                progress_line = progress_line[:max_length] + "..."
        
        print(progress_line, end='', flush=True)
    
    def increment(self, message: str = '') -> None:
        """
        Increment progress by 1
        
        Args:
            message: Optional message to display
        """
        self.update(self.current + 1, message)
    
    def finish(self, message: str = 'Complete') -> None:
        """
        Complete progress bar
        
        Args:
            message: Completion message
        """
        self.update(self.total, message)
        print()  # New line after completion
    
    def _format_time(self, seconds: float) -> str:
        """Format time duration as human-readable string"""
        if seconds < 60:
            return f"{seconds:.0f}s"
        elif seconds < 3600:
            return f"{seconds/60:.0f}m {seconds%60:.0f}s"
        else:
            hours = seconds // 3600
            minutes = (seconds % 3600) // 60
            return f"{hours:.0f}h {minutes:.0f}m"


class Menu:
    """Interactive menu system with keyboard navigation"""
    
    def __init__(self, title: str, options: List[str], multi_select: bool = False):
        """
        Initialize menu
        
        Args:
            title: Menu title
            options: List of menu options
            multi_select: Allow multiple selections
        """
        self.title = title
        self.options = options
        self.multi_select = multi_select
        self.selected = set() if multi_select else None
        
    def display(self) -> Union[int, List[int]]:
        """
        Display menu and get user selection
        
        Returns:
            Selected option index (single) or list of indices (multi-select)
        """
        print(f"\n{Colors.CYAN}{Colors.BRIGHT}{self.title}{Colors.RESET}")
        print("=" * len(self.title))
        
        for i, option in enumerate(self.options, 1):
            if self.multi_select:
                marker = "[x]" if i-1 in (self.selected or set()) else "[ ]"
                print(f"{Colors.YELLOW}{i:2d}.{Colors.RESET} {marker} {option}")
            else:
                print(f"{Colors.YELLOW}{i:2d}.{Colors.RESET} {option}")
        
        if self.multi_select:
            print(f"\n{Colors.BLUE}Enter numbers separated by commas (e.g., 1,3,5) or 'all' for all options:{Colors.RESET}")
        else:
            print(f"\n{Colors.BLUE}Enter your choice (1-{len(self.options)}):{Colors.RESET}")
        
        while True:
            try:
                user_input = input("> ").strip().lower()
                
                if self.multi_select:
                    if user_input == 'all':
                        return list(range(len(self.options)))
                    elif user_input == '':
                        return []
                    else:
                        # Parse comma-separated numbers
                        selections = []
                        for part in user_input.split(','):
                            part = part.strip()
                            if part.isdigit():
                                idx = int(part) - 1
                                if 0 <= idx < len(self.options):
                                    selections.append(idx)
                                else:
                                    raise ValueError(f"Invalid option: {part}")
                            else:
                                raise ValueError(f"Invalid input: {part}")
                        return list(set(selections))  # Remove duplicates
                else:
                    if user_input.isdigit():
                        choice = int(user_input) - 1
                        if 0 <= choice < len(self.options):
                            return choice
                        else:
                            print(f"{Colors.RED}Invalid choice. Please enter a number between 1 and {len(self.options)}.{Colors.RESET}")
                    else:
                        print(f"{Colors.RED}Please enter a valid number.{Colors.RESET}")
                        
            except (ValueError, KeyboardInterrupt) as e:
                if isinstance(e, KeyboardInterrupt):
                    print(f"\n{Colors.YELLOW}Operation cancelled.{Colors.RESET}")
                    return [] if self.multi_select else -1
                else:
                    print(f"{Colors.RED}Invalid input: {e}{Colors.RESET}")


def confirm(message: str, default: bool = True) -> bool:
    """
    Ask for user confirmation
    
    Args:
        message: Confirmation message
        default: Default response if user just presses Enter
        
    Returns:
        True if confirmed, False otherwise
    """
    suffix = "[Y/n]" if default else "[y/N]"
    print(f"{Colors.BLUE}{message} {suffix}{Colors.RESET}")
    
    while True:
        try:
            response = input("> ").strip().lower()
            
            if response == '':
                return default
            elif response in ['y', 'yes', 'true', '1']:
                return True
            elif response in ['n', 'no', 'false', '0']:
                return False
            else:
                print(f"{Colors.RED}Please enter 'y' or 'n' (or press Enter for default).{Colors.RESET}")
                
        except KeyboardInterrupt:
            print(f"\n{Colors.YELLOW}Operation cancelled.{Colors.RESET}")
            return False


def display_header(title: str, subtitle: str = '') -> None:
    """
    Display formatted header
    
    Args:
        title: Main title
        subtitle: Optional subtitle
    """
    print(f"\n{Colors.CYAN}{Colors.BRIGHT}{'='*60}{Colors.RESET}")
    print(f"{Colors.CYAN}{Colors.BRIGHT}{title:^60}{Colors.RESET}")
    if subtitle:
        print(f"{Colors.WHITE}{subtitle:^60}{Colors.RESET}")
    print(f"{Colors.CYAN}{Colors.BRIGHT}{'='*60}{Colors.RESET}\n")


def display_info(message: str) -> None:
    """Display info message"""
    print(f"{Colors.BLUE}[INFO] {message}{Colors.RESET}")


def display_success(message: str) -> None:
    """Display success message"""
    print(f"{Colors.GREEN}[✓] {message}{Colors.RESET}")


def display_warning(message: str) -> None:
    """Display warning message"""
    print(f"{Colors.YELLOW}[!] {message}{Colors.RESET}")


def display_error(message: str) -> None:
    """Display error message"""
    print(f"{Colors.RED}[✗] {message}{Colors.RESET}")


def display_step(step: int, total: int, message: str) -> None:
    """Display step progress"""
    print(f"{Colors.CYAN}[{step}/{total}] {message}{Colors.RESET}")


def display_table(headers: List[str], rows: List[List[str]], title: str = '') -> None:
    """
    Display data in table format
    
    Args:
        headers: Column headers
        rows: Data rows
        title: Optional table title
    """
    if not rows:
        return
    
    # Calculate column widths
    col_widths = [len(header) for header in headers]
    for row in rows:
        for i, cell in enumerate(row):
            if i < len(col_widths):
                col_widths[i] = max(col_widths[i], len(str(cell)))
    
    # Display title
    if title:
        print(f"\n{Colors.CYAN}{Colors.BRIGHT}{title}{Colors.RESET}")
        print()
    
    # Display headers
    header_line = " | ".join(f"{header:<{col_widths[i]}}" for i, header in enumerate(headers))
    print(f"{Colors.YELLOW}{header_line}{Colors.RESET}")
    print("-" * len(header_line))
    
    # Display rows
    for row in rows:
        row_line = " | ".join(f"{str(cell):<{col_widths[i]}}" for i, cell in enumerate(row))
        print(row_line)
    
    print()


def wait_for_key(message: str = "Press Enter to continue...") -> None:
    """Wait for user to press a key"""
    try:
        input(f"{Colors.BLUE}{message}{Colors.RESET}")
    except KeyboardInterrupt:
        print(f"\n{Colors.YELLOW}Operation cancelled.{Colors.RESET}")


def clear_screen() -> None:
    """Clear terminal screen"""
    import os
    os.system('cls' if os.name == 'nt' else 'clear')


class StatusSpinner:
    """Simple status spinner for long operations"""
    
    def __init__(self, message: str = "Working..."):
        """
        Initialize spinner
        
        Args:
            message: Message to display with spinner
        """
        self.message = message
        self.spinning = False
        self.chars = "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"
        self.current = 0
    
    def start(self) -> None:
        """Start spinner in background thread"""
        import threading
        
        def spin():
            while self.spinning:
                char = self.chars[self.current % len(self.chars)]
                print(f"\r{Colors.BLUE}{char} {self.message}{Colors.RESET}", end='', flush=True)
                self.current += 1
                time.sleep(0.1)
        
        self.spinning = True
        self.thread = threading.Thread(target=spin, daemon=True)
        self.thread.start()
    
    def stop(self, final_message: str = '') -> None:
        """
        Stop spinner
        
        Args:
            final_message: Final message to display
        """
        self.spinning = False
        if hasattr(self, 'thread'):
            self.thread.join(timeout=0.2)
        
        # Clear spinner line
        print(f"\r{' ' * (len(self.message) + 5)}\r", end='')
        
        if final_message:
            print(final_message)


def format_size(size_bytes: int) -> str:
    """Format file size in human-readable format"""
    for unit in ['B', 'KB', 'MB', 'GB', 'TB']:
        if size_bytes < 1024.0:
            return f"{size_bytes:.1f} {unit}"
        size_bytes /= 1024.0
    return f"{size_bytes:.1f} PB"


def format_duration(seconds: float) -> str:
    """Format duration in human-readable format"""
    if seconds < 1:
        return f"{seconds*1000:.0f}ms"
    elif seconds < 60:
        return f"{seconds:.1f}s"
    elif seconds < 3600:
        minutes = seconds // 60
        secs = seconds % 60
        return f"{minutes:.0f}m {secs:.0f}s"
    else:
        hours = seconds // 3600
        minutes = (seconds % 3600) // 60
        return f"{hours:.0f}h {minutes:.0f}m"


def truncate_text(text: str, max_length: int, suffix: str = "...") -> str:
    """Truncate text to maximum length with optional suffix"""
    if len(text) <= max_length:
        return text
    
    return text[:max_length - len(suffix)] + suffix
