"""
Application settings and configuration management.

This module handles application-wide settings, preferences, and configuration
data. It provides a centralized location for managing user preferences,
default values, and application state.

Main Components:
    - Settings class for configuration management
    - Default configuration values
    - Settings persistence and loading
    - Configuration validation

Usage:
    from cluster4npu_ui.config.settings import Settings
    
    settings = Settings()
    recent_files = settings.get_recent_files()
    settings.add_recent_file('/path/to/pipeline.mflow')
"""

import json
import os
from typing import Dict, Any, List, Optional
from pathlib import Path


class Settings:
    """
    Application settings and configuration management.
    
    Handles loading, saving, and managing application settings including
    user preferences, recent files, and default configurations.
    """
    
    def __init__(self, config_file: Optional[str] = None):
        """
        Initialize settings manager.
        
        Args:
            config_file: Optional path to configuration file
        """
        self.config_file = config_file or self._get_default_config_path()
        self._settings = self._load_default_settings()
        self.load()
    
    def _get_default_config_path(self) -> str:
        """Get the default configuration file path."""
        home_dir = Path.home()
        config_dir = home_dir / '.cluster4npu'
        config_dir.mkdir(exist_ok=True)
        return str(config_dir / 'settings.json')
    
    def _load_default_settings(self) -> Dict[str, Any]:
        """Load default application settings."""
        return {
            'general': {
                'auto_save': True,
                'auto_save_interval': 300,  # seconds
                'check_for_updates': True,
                'theme': 'harmonious_dark',
                'language': 'en'
            },
            'recent_files': [],
            'window': {
                'main_window_geometry': None,
                'main_window_state': None,
                'splitter_sizes': None,
                'recent_window_size': [1200, 800]
            },
            'pipeline': {
                'default_project_location': str(Path.home() / 'Documents' / 'Cluster4NPU'),
                'auto_layout': True,
                'show_grid': True,
                'snap_to_grid': False,
                'grid_size': 20,
                'auto_connect': True,
                'validate_on_save': True
            },
            'performance': {
                'max_undo_steps': 50,
                'render_quality': 'high',
                'enable_animations': True,
                'cache_size_mb': 100
            },
            'hardware': {
                'auto_detect_dongles': True,
                'preferred_dongle_series': '720',
                'max_dongles_per_stage': 4,
                'power_management': 'balanced'
            },
            'export': {
                'default_format': 'JSON',
                'include_metadata': True,
                'compress_exports': False,
                'export_location': str(Path.home() / 'Downloads')
            },
            'debugging': {
                'log_level': 'INFO',
                'enable_profiling': False,
                'save_debug_logs': False,
                'max_log_files': 10
            }
        }
    
    def load(self) -> bool:
        """
        Load settings from file.
        
        Returns:
            True if settings were loaded successfully, False otherwise
        """
        try:
            if os.path.exists(self.config_file):
                with open(self.config_file, 'r', encoding='utf-8') as f:
                    saved_settings = json.load(f)
                    self._merge_settings(saved_settings)
                return True
        except Exception as e:
            print(f"Error loading settings: {e}")
        return False
    
    def save(self) -> bool:
        """
        Save current settings to file.
        
        Returns:
            True if settings were saved successfully, False otherwise
        """
        try:
            os.makedirs(os.path.dirname(self.config_file), exist_ok=True)
            with open(self.config_file, 'w', encoding='utf-8') as f:
                json.dump(self._settings, f, indent=2, ensure_ascii=False)
            return True
        except Exception as e:
            print(f"Error saving settings: {e}")
            return False
    
    def _merge_settings(self, saved_settings: Dict[str, Any]):
        """Merge saved settings with defaults."""
        def merge_dict(default: dict, saved: dict) -> dict:
            result = default.copy()
            for key, value in saved.items():
                if key in result and isinstance(result[key], dict) and isinstance(value, dict):
                    result[key] = merge_dict(result[key], value)
                else:
                    result[key] = value
            return result
        
        self._settings = merge_dict(self._settings, saved_settings)
    
    def get(self, key: str, default: Any = None) -> Any:
        """
        Get a setting value using dot notation.
        
        Args:
            key: Setting key (e.g., 'general.auto_save')
            default: Default value if key not found
            
        Returns:
            Setting value or default
        """
        keys = key.split('.')
        value = self._settings
        
        try:
            for k in keys:
                value = value[k]
            return value
        except (KeyError, TypeError):
            return default
    
    def set(self, key: str, value: Any):
        """
        Set a setting value using dot notation.
        
        Args:
            key: Setting key (e.g., 'general.auto_save')
            value: Value to set
        """
        keys = key.split('.')
        setting = self._settings
        
        # Navigate to the parent dictionary
        for k in keys[:-1]:
            if k not in setting:
                setting[k] = {}
            setting = setting[k]
        
        # Set the final value
        setting[keys[-1]] = value
    
    def get_recent_files(self) -> List[str]:
        """Get list of recent files."""
        return self.get('recent_files', [])
    
    def add_recent_file(self, file_path: str, max_files: int = 10):
        """
        Add a file to recent files list.
        
        Args:
            file_path: Path to the file
            max_files: Maximum number of recent files to keep
        """
        recent_files = self.get_recent_files()
        
        # Remove if already exists
        if file_path in recent_files:
            recent_files.remove(file_path)
        
        # Add to beginning
        recent_files.insert(0, file_path)
        
        # Limit list size
        recent_files = recent_files[:max_files]
        
        self.set('recent_files', recent_files)
        self.save()
    
    def remove_recent_file(self, file_path: str):
        """Remove a file from recent files list."""
        recent_files = self.get_recent_files()
        if file_path in recent_files:
            recent_files.remove(file_path)
            self.set('recent_files', recent_files)
            self.save()
    
    def clear_recent_files(self):
        """Clear all recent files."""
        self.set('recent_files', [])
        self.save()
    
    def get_default_project_location(self) -> str:
        """Get default project location."""
        return self.get('pipeline.default_project_location', str(Path.home() / 'Documents' / 'Cluster4NPU'))
    
    def set_window_geometry(self, geometry: bytes):
        """Save window geometry."""
        # Convert bytes to base64 string for JSON serialization
        import base64
        geometry_str = base64.b64encode(geometry).decode('utf-8')
        self.set('window.main_window_geometry', geometry_str)
        self.save()
    
    def get_window_geometry(self) -> Optional[bytes]:
        """Get saved window geometry."""
        geometry_str = self.get('window.main_window_geometry')
        if geometry_str:
            import base64
            return base64.b64decode(geometry_str.encode('utf-8'))
        return None
    
    def set_window_state(self, state: bytes):
        """Save window state."""
        import base64
        state_str = base64.b64encode(state).decode('utf-8')
        self.set('window.main_window_state', state_str)
        self.save()
    
    def get_window_state(self) -> Optional[bytes]:
        """Get saved window state."""
        state_str = self.get('window.main_window_state')
        if state_str:
            import base64
            return base64.b64decode(state_str.encode('utf-8'))
        return None
    
    def reset_to_defaults(self):
        """Reset all settings to default values."""
        self._settings = self._load_default_settings()
        self.save()
    
    def export_settings(self, file_path: str) -> bool:
        """
        Export settings to a file.
        
        Args:
            file_path: Path to export file
            
        Returns:
            True if export was successful, False otherwise
        """
        try:
            with open(file_path, 'w', encoding='utf-8') as f:
                json.dump(self._settings, f, indent=2, ensure_ascii=False)
            return True
        except Exception as e:
            print(f"Error exporting settings: {e}")
            return False
    
    def import_settings(self, file_path: str) -> bool:
        """
        Import settings from a file.
        
        Args:
            file_path: Path to import file
            
        Returns:
            True if import was successful, False otherwise
        """
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                imported_settings = json.load(f)
                self._merge_settings(imported_settings)
                self.save()
            return True
        except Exception as e:
            print(f"Error importing settings: {e}")
            return False


# Global settings instance
_settings_instance = None


def get_settings() -> Settings:
    """Get the global settings instance."""
    global _settings_instance
    if _settings_instance is None:
        _settings_instance = Settings()
    return _settings_instance