"""
Configuration manager for data augmentation
"""
import yaml
import os
from pathlib import Path
from typing import Dict, Any, Optional, Union

class ConfigManager:
    """Manages configuration loading and validation"""
    
    def __init__(self, config_path: Optional[Union[str, Path]] = None):
        """
        Initialize ConfigManager
        
        Args:
            config_path: Path to main config file
        """
        self.config_path = Path(config_path) if config_path else Path("config/config.yaml")
        self.config = {}
        
        self._load_config()
    
    def _load_config(self):
        """Load main configuration file"""
        try:
            if self.config_path.exists():
                with open(self.config_path, 'r', encoding='utf-8') as f:
                    self.config = yaml.safe_load(f)
                print(f"✅ Loaded configuration from {self.config_path}")
            else:
                print(f"⚠️  Config file not found: {self.config_path}")
                self.config = self._get_default_config()
        except Exception as e:
            print(f"❌ Error loading config: {e}")
            self.config = self._get_default_config()
    
    def _get_default_config(self) -> Dict[str, Any]:
        """Get default configuration"""
        return {
            "paths": {
                "input_dir": "data/dataset/training_data/images",
                "output_dir": "data/augmented_data",
                "log_file": "logs/data_augmentation.log"
            },
            "augmentation": {
                "rotation": {"enabled": True, "angles": [30, 60, 120, 150, 180, 210, 240, 300, 330], "probability": 1.0},
                "random_cropping": {"enabled": True, "ratio_range": [0.7, 1.0], "probability": 1.0},
                "random_noise": {"enabled": True, "mean_range": [0.0, 0.7], "variance_range": [0.0, 0.1], "probability": 1.0},
                "partial_blockage": {"enabled": True, "num_occlusions_range": [1, 100], "coverage_range": [0.0, 0.25], "variance_range": [0.0, 0.1], "probability": 1.0},
                "grayscale": {"enabled": True, "probability": 1.0},
                "blurring": {"enabled": True, "kernel_ratio_range": [0.0, 0.0084], "probability": 1.0},
                "brightness_contrast": {"enabled": True, "alpha_range": [0.4, 3.0], "beta_range": [1, 100], "probability": 1.0}
            },
            "processing": {
                "target_size": [224, 224],
                "batch_size": 32,
                "num_augmentations": 3,
                "save_format": "jpg",
                "quality": 95
            },
            "supported_formats": [".jpg", ".jpeg", ".png", ".bmp", ".tiff"],
            "logging": {
                "level": "INFO",
                "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
            },
            "performance": {
                "num_workers": 4,
                "prefetch_factor": 2,
                "pin_memory": True,
                "use_gpu": False
            }
        }
    
    def get_config(self) -> Dict[str, Any]:
        """Get current configuration"""
        return self.config
    
    def get_augmentation_config(self) -> Dict[str, Any]:
        """Get augmentation configuration"""
        return self.config.get("augmentation", {})
    
    def get_processing_config(self) -> Dict[str, Any]:
        """Get processing configuration"""
        return self.config.get("processing", {})
    
    def get_paths_config(self) -> Dict[str, Any]:
        """Get paths configuration"""
        return self.config.get("paths", {})
    
    def get_logging_config(self) -> Dict[str, Any]:
        """Get logging configuration"""
        return self.config.get("logging", {})
    
    def get_performance_config(self) -> Dict[str, Any]:
        """Get performance configuration"""
        return self.config.get("performance", {})
    

    
    def update_config(self, updates: Dict[str, Any]) -> bool:
        """
        Update configuration with new values
        
        Args:
            updates: Dictionary with updates to apply
            
        Returns:
            True if updated successfully
        """
        try:
            self.config = self._merge_configs(self.config, updates)
            return True
        except Exception as e:
            print(f"❌ Error updating config: {e}")
            return False
    
    def _merge_configs(self, base_config: Dict[str, Any], updates: Dict[str, Any]) -> Dict[str, Any]:
        """Merge updates with base configuration"""
        merged = base_config.copy()
        
        def deep_merge(base: Dict[str, Any], update: Dict[str, Any]) -> Dict[str, Any]:
            result = base.copy()
            for key, value in update.items():
                if key in result and isinstance(result[key], dict) and isinstance(value, dict):
                    result[key] = deep_merge(result[key], value)
                else:
                    result[key] = value
            return result
        
        return deep_merge(merged, updates)
    
    def save_config(self, output_path: Optional[Union[str, Path]] = None) -> bool:
        """
        Save current configuration to file
        
        Args:
            output_path: Path to save config file
            
        Returns:
            True if saved successfully
        """
        try:
            output_path = Path(output_path) if output_path else self.config_path
            output_path.parent.mkdir(parents=True, exist_ok=True)
            
            with open(output_path, 'w', encoding='utf-8') as f:
                yaml.dump(self.config, f, default_flow_style=False, indent=2, allow_unicode=True)
            
            print(f"✅ Configuration saved to {output_path}")
            return True
        except Exception as e:
            print(f"❌ Error saving config: {e}")
            return False
    
    def print_config_summary(self):
        """Print configuration summary"""
        print("\n" + "="*50)
        print("CONFIGURATION SUMMARY")
        print("="*50)
        
        # Paths
        paths = self.get_paths_config()
        print(f"Input directory: {paths.get('input_dir', 'Not set')}")
        print(f"Output directory: {paths.get('output_dir', 'Not set')}")
        
        # Processing
        processing = self.get_processing_config()
        print(f"Target size: {processing.get('target_size', 'Not set')}")
        print(f"Number of augmentations: {processing.get('num_augmentations', 'Not set')}")
        
        # Augmentation
        augmentation = self.get_augmentation_config()
        enabled_augmentations = []
        for name, config in augmentation.items():
            if isinstance(config, dict) and config.get('enabled', False):
                enabled_augmentations.append(name)
        
        print(f"Enabled augmentations: {', '.join(enabled_augmentations) if enabled_augmentations else 'None'}")
        
        print("="*50) 