"""
Theme system for MiniMax CLI.

Provides centralized theme configuration with support for dark/light modes,
consistent color schemes, icon sets, and styling across all presentation layers.
"""

import os
import json
from typing import Dict, Any, Optional, Union
from dataclasses import dataclass, asdict
from enum import Enum
from pathlib import Path


class ThemeMode(Enum):
    """Theme mode enumeration."""
    DARK = "dark"
    LIGHT = "light"
    AUTO = "auto"


@dataclass
class ThemeColors:
    """Color scheme for the theme."""
    # Primary colors
    primary: str
    primary_hover: str
    primary_active: str
    
    # Secondary/accent colors
    accent: str
    accent_hover: str
    accent_active: str
    
    # Surface colors
    surface: str
    surface_variant: str
    surface_container: str
    surface_container_high: str
    
    # Background colors
    background: str
    background_variant: str
    
    # Text colors
    text_primary: str
    text_secondary: str
    text_tertiary: str
    text_disabled: str
    
    # Status colors
    success: str
    warning: str
    error: str
    info: str
    
    # Border colors
    border: str
    border_variant: str
    border_focus: str
    
    # Special colors
    shadow: str
    overlay: str


@dataclass
class ThemeIcons:
    """Icon set for the theme."""
    # General icons
    logo: str = "🤖"
    chat: str = "💬"
    analyze: str = "🔍"
    generate: str = "⚡"
    edit: str = "✏️"
    project: str = "📁"
    help: str = "❓"
    settings: str = "⚙️"
    
    # Status icons
    success: str = "✅"
    warning: str = "⚠️"
    error: str = "❌"
    info: str = "ℹ️"
    loading: str = "⏳"
    
    # Action icons
    search: str = "🔍"
    filter: str = "📊"
    sort: str = "📈"
    refresh: str = "🔄"
    save: str = "💾"
    load: str = "📂"
    export: str = "📤"
    import_: str = "📥"
    
    # File type icons
    file_code: str = "📄"
    file_python: str = "🐍"
    file_javascript: str = "📜"
    file_typescript: str = "📘"
    file_html: str = "🌐"
    file_css: str = "🎨"
    file_json: str = "📋"
    file_yaml: str = "📄"
    file_markdown: str = "📝"
    file_image: str = "🖼️"
    file_archive: str = "📦"
    folder: str = "📁"
    folder_open: str = "📂"
    
    # Navigation icons
    arrow_left: str = "←"
    arrow_right: str = "→"
    arrow_up: str = "↑"
    arrow_down: str = "↓"
    chevron_left: str = "‹"
    chevron_right: str = "›"
    chevron_up: str = "^"
    chevron_down: str = "v"
    
    # UI elements
    menu: str = "☰"
    close: str = "✕"
    minimize: str = "−"
    maximize: str = "□"
    restore: str = "⧉"
    pin: str = "📌"
    unpin: str = "📍"


@dataclass
class ThemeStyles:
    """Text and component styles for the theme."""
    # Font families
    font_mono: str = "Menlo, Monaco, 'Courier New', monospace"
    font_sans: str = "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"
    
    # Font sizes
    text_xs: str = "0.75rem"
    text_sm: str = "0.875rem"
    text_base: str = "1rem"
    text_lg: str = "1.125rem"
    text_xl: str = "1.25rem"
    text_2xl: str = "1.5rem"
    text_3xl: str = "1.875rem"
    
    # Border styles
    border_radius_sm: str = "2px"
    border_radius: str = "4px"
    border_radius_lg: str = "8px"
    border_radius_xl: str = "12px"
    border_width: str = "1px"
    border_width_thick: str = "2px"
    
    # Spacing
    spacing_xs: str = "0.25rem"
    spacing_sm: str = "0.5rem"
    spacing_md: str = "1rem"
    spacing_lg: str = "1.5rem"
    spacing_xl: str = "2rem"
    spacing_2xl: str = "3rem"
    
    # Animation durations
    duration_fast: str = "150ms"
    duration_normal: str = "300ms"
    duration_slow: str = "500ms"
    
    # Z-index layers
    z_dropdown: int = 1000
    z_sticky: int = 1010
    z_fixed: int = 1020
    z_modal_backdrop: int = 1030
    z_modal: int = 1040
    z_popover: int = 1050
    z_tooltip: int = 1060


@dataclass
class Theme:
    """Complete theme configuration."""
    name: str
    mode: ThemeMode
    colors: ThemeColors
    icons: ThemeIcons
    styles: ThemeStyles
    
    def to_dict(self) -> Dict[str, Any]:
        """Convert theme to dictionary."""
        result = asdict(self)
        # Convert ThemeMode enum to string for JSON serialization
        result['mode'] = self.mode.value
        return result
    
    def get_css_variables(self) -> Dict[str, str]:
        """Generate CSS variables from theme."""
        variables = {}
        
        # Add color variables
        for key, value in asdict(self.colors).items():
            variables[f"--color-{key.replace('_', '-')}"] = value
        
        # Add style variables
        for key, value in asdict(self.styles).items():
            if isinstance(value, str):
                variables[f"--{key.replace('_', '-')}"] = value
            elif isinstance(value, int):
                variables[f"--{key.replace('_', '-')}"] = str(value)
        
        return variables


# Default theme configurations
DARK_COLORS = ThemeColors(
    # Primary colors
    primary="#3B82F6",
    primary_hover="#2563EB",
    primary_active="#1D4ED8",
    
    # Accent colors
    accent="#8B5CF6",
    accent_hover="#7C3AED",
    accent_active="#6D28D9",
    
    # Surface colors
    surface="#1F2937",
    surface_variant="#374151",
    surface_container="#4B5563",
    surface_container_high="#6B7280",
    
    # Background colors
    background="#111827",
    background_variant="#1F2937",
    
    # Text colors
    text_primary="#F9FAFB",
    text_secondary="#E5E7EB",
    text_tertiary="#9CA3AF",
    text_disabled="#6B7280",
    
    # Status colors
    success="#10B981",
    warning="#F59E0B",
    error="#EF4444",
    info="#3B82F6",
    
    # Border colors
    border="#374151",
    border_variant="#4B5563",
    border_focus="#3B82F6",
    
    # Special colors
    shadow="rgba(0, 0, 0, 0.5)",
    overlay="rgba(0, 0, 0, 0.6)"
)

LIGHT_COLORS = ThemeColors(
    # Primary colors
    primary="#2563EB",
    primary_hover="#1D4ED8",
    primary_active="#1E40AF",
    
    # Accent colors
    accent="#7C3AED",
    accent_hover="#6D28D9",
    accent_active="#5B21B6",
    
    # Surface colors
    surface="#FFFFFF",
    surface_variant="#F9FAFB",
    surface_container="#F3F4F6",
    surface_container_high="#E5E7EB",
    
    # Background colors
    background="#FFFFFF",
    background_variant="#F9FAFB",
    
    # Text colors
    text_primary="#111827",
    text_secondary="#374151",
    text_tertiary="#6B7280",
    text_disabled="#9CA3AF",
    
    # Status colors
    success="#059669",
    warning="#D97706",
    error="#DC2626",
    info="#2563EB",
    
    # Border colors
    border="#E5E7EB",
    border_variant="#D1D5DB",
    border_focus="#2563EB",
    
    # Special colors
    shadow="rgba(0, 0, 0, 0.1)",
    overlay="rgba(0, 0, 0, 0.3)"
)

DEFAULT_STYLES = ThemeStyles()
DEFAULT_ICONS = ThemeIcons()

# Default themes
DARK_THEME = Theme(
    name="dark",
    mode=ThemeMode.DARK,
    colors=DARK_COLORS,
    icons=DEFAULT_ICONS,
    styles=DEFAULT_STYLES
)

LIGHT_THEME = Theme(
    name="light",
    mode=ThemeMode.LIGHT,
    colors=LIGHT_COLORS,
    icons=DEFAULT_ICONS,
    styles=DEFAULT_STYLES
)

# Global theme state
_current_theme: Optional[Theme] = None
_theme_config_path: Optional[Path] = None


def get_theme_config_path() -> Path:
    """Get the path to the theme configuration file."""
    global _theme_config_path
    if _theme_config_path is None:
        # Try to find config in various locations
        config_dir = Path.home() / ".config" / "minimax"
        config_dir.mkdir(parents=True, exist_ok=True)
        _theme_config_path = config_dir / "theme.json"
    return _theme_config_path


def load_theme_config() -> Theme:
    """Load theme configuration from file or use default."""
    global _current_theme
    
    config_path = get_theme_config_path()
    
    # Try to load from file
    if config_path.exists():
        try:
            with open(config_path, 'r', encoding='utf-8') as f:
                config_data = json.load(f)
            
            # Extract theme components
            mode = ThemeMode(config_data.get('mode', 'dark'))
            colors = ThemeColors(**config_data.get('colors', asdict(DARK_COLORS)))
            icons = ThemeIcons(**config_data.get('icons', asdict(DEFAULT_ICONS)))
            styles = ThemeStyles(**config_data.get('styles', asdict(DEFAULT_STYLES)))
            
            _current_theme = Theme(
                name=config_data.get('name', mode.value),
                mode=mode,
                colors=colors,
                icons=icons,
                styles=styles
            )
            
        except Exception as e:
            print(f"Warning: Failed to load theme config: {e}")
            _current_theme = DARK_THEME
    else:
        # Use default theme based on environment or system preference
        theme_name = os.environ.get('MINIMAX_THEME', 'dark').lower()
        if theme_name == 'light':
            _current_theme = LIGHT_THEME
        else:
            _current_theme = DARK_THEME
    
    return _current_theme


def save_theme_config(theme: Theme) -> bool:
    """Save theme configuration to file."""
    try:
        config_path = get_theme_config_path()
        config_path.parent.mkdir(parents=True, exist_ok=True)
        
        with open(config_path, 'w', encoding='utf-8') as f:
            json.dump(theme.to_dict(), f, indent=2)
        
        return True
    except Exception as e:
        print(f"Warning: Failed to save theme config: {e}")
        return False


def get_theme_config() -> Theme:
    """Get the current theme configuration."""
    global _current_theme
    if _current_theme is None:
        _current_theme = load_theme_config()
    return _current_theme


def set_theme(theme_name_or_mode: Union[str, ThemeMode, Theme]) -> Theme:
    """Set the current theme."""
    global _current_theme
    
    if isinstance(theme_name_or_mode, Theme):
        _current_theme = theme_name_or_mode
    elif isinstance(theme_name_or_mode, ThemeMode):
        _current_theme = DARK_THEME if theme_name_or_mode == ThemeMode.DARK else LIGHT_THEME
    else:
        # String theme name
        theme_name = str(theme_name_or_mode).lower()
        if theme_name in ('light', 'day'):
            _current_theme = LIGHT_THEME
        else:
            _current_theme = DARK_THEME
    
    # Save the new theme
    save_theme_config(_current_theme)
    
    return _current_theme


def get_color(color_name: str, opacity: Optional[float] = None) -> str:
    """Get a color value from the current theme."""
    theme = get_theme_config()
    color_value = getattr(theme.colors, color_name, None)
    
    if color_value is None:
        # Fallback to default color
        return "#FFFFFF" if theme.mode == ThemeMode.DARK else "#000000"
    
    # Apply opacity if specified
    if opacity is not None and 0.0 <= opacity <= 1.0:
        if color_value.startswith('#') and len(color_value) == 7:
            # Convert hex to rgba
            hex_color = color_value[1:]
            r = int(hex_color[0:2], 16)
            g = int(hex_color[2:4], 16)
            b = int(hex_color[4:6], 16)
            return f"rgba({r}, {g}, {b}, {opacity})"
    
    return color_value


def get_icon(icon_name: str) -> str:
    """Get an icon from the current theme."""
    theme = get_theme_config()
    return getattr(theme.icons, icon_name, "•")


def get_style(style_name: str) -> str:
    """Get a style value from the current theme."""
    theme = get_theme_config()
    return getattr(theme.styles, style_name, "")


def get_file_icon(filename: str) -> str:
    """Get appropriate icon for a file based on its extension."""
    theme = get_theme_config()
    
    if not filename:
        return theme.icons.file_code
    
    # Convert to lowercase for comparison
    name_lower = filename.lower()
    
    # Check for exact filename matches first
    if name_lower in ('readme.md', 'readme.txt', 'readme'):
        return theme.icons.file_markdown
    
    # Check by extension
    if '.' in filename:
        ext = name_lower.split('.')[-1]
        icon_map = {
            'py': theme.icons.file_python,
            'js': theme.icons.file_javascript,
            'ts': theme.icons.file_typescript,
            'html': theme.icons.file_html,
            'css': theme.icons.file_css,
            'scss': theme.icons.file_css,
            'sass': theme.icons.file_css,
            'json': theme.icons.file_json,
            'yaml': theme.icons.file_yaml,
            'yml': theme.icons.file_yaml,
            'md': theme.icons.file_markdown,
            'markdown': theme.icons.file_markdown,
            'png': theme.icons.file_image,
            'jpg': theme.icons.file_image,
            'jpeg': theme.icons.file_image,
            'gif': theme.icons.file_image,
            'svg': theme.icons.file_image,
            'zip': theme.icons.file_archive,
            'tar': theme.icons.file_archive,
            'gz': theme.icons.file_archive,
            'bz2': theme.icons.file_archive,
            'rar': theme.icons.file_archive,
        }
        return icon_map.get(ext, theme.icons.file_code)
    
    return theme.icons.file_code


def get_css_variables() -> Dict[str, str]:
    """Get CSS variables for the current theme."""
    theme = get_theme_config()
    return theme.get_css_variables()


def create_custom_theme(name: str, base_theme: Theme, **overrides) -> Theme:
    """Create a custom theme based on an existing theme with overrides."""
    theme_dict = base_theme.to_dict()
    
    # Apply overrides
    for key, value in overrides.items():
        if '.' in key:
            # Nested key like 'colors.primary'
            parts = key.split('.')
            current = theme_dict
            for part in parts[:-1]:
                if part not in current:
                    current[part] = {}
                current = current[part]
            current[parts[-1]] = value
        else:
            theme_dict[key] = value
    
    # Reconstruct theme
    colors = ThemeColors(**theme_dict['colors'])
    icons = ThemeIcons(**theme_dict['icons'])
    styles = ThemeStyles(**theme_dict['styles'])
    
    return Theme(
        name=name,
        mode=ThemeMode(theme_dict['mode']),
        colors=colors,
        icons=icons,
        styles=styles
    )


# Initialize default theme on import
load_theme_config()


__all__ = [
    'Theme', 'ThemeMode', 'ThemeColors', 'ThemeIcons', 'ThemeStyles',
    'DARK_THEME', 'LIGHT_THEME',
    'load_theme_config', 'save_theme_config', 'get_theme_config', 'set_theme',
    'get_color', 'get_icon', 'get_style', 'get_file_icon', 'get_css_variables',
    'create_custom_theme'
]