"""
Configuration module for Data Cleaning Pipeline
"""

from dataclasses import dataclass, field
from enum import Enum
from pathlib import Path
from typing import Optional, Dict, Any, Union
import yaml
import logging

# ============================================================================
# ENUMS
# ============================================================================

class ImputationStrategy(Enum):
    """Supported missing value imputation strategies"""
    DROP = "drop"
    MEAN = "mean"
    MEDIAN = "median"
    MODE = "mode"
    FORWARD_FILL = "ffill"
    BACKWARD_FILL = "bfill"
    CONSTANT = "constant"
    INTERPOLATE = "interpolate"


class OutlierMethod(Enum):
    """Supported outlier detection methods"""
    IQR = "iqr"
    ZSCORE = "zscore"
    MODIFIED_ZSCORE = "modified_zscore"
    ISOLATION_FOREST = "isolation_forest"


# ============================================================================
# EXCEPTIONS
# ============================================================================

class ConfigurationError(Exception):
    """Raised when configuration is invalid"""
    pass


# ============================================================================
# CONFIGURATION CLASS
# ============================================================================

@dataclass
class PipelineConfig:
    """Configuration for the data cleaning pipeline"""
    
    # General Settings
    log_level: str = "INFO"
    log_file: Optional[Path] = None
    enable_profiling: bool = False
    strict_mode: bool = False
    
    # Performance
    chunk_size: Optional[int] = None
    max_memory_mb: int = 2048
    
    # Validation & Quality
    enable_validation: bool = True
    min_quality_score: float = 0.0
    
    # Checkpointing
    checkpoint_dir: Optional[Path] = None
    max_checkpoints: int = 10
    
    # Security
    allow_custom_functions: bool = False
    allow_file_operations: bool = False
    
    # Advanced
    enable_metrics: bool = True
    
    def __post_init__(self):
        """Validate configuration settings"""
        # Validate log level
        valid_levels = {'DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'}
        if self.log_level.upper() not in valid_levels:
            raise ConfigurationError(f"Invalid log_level: {self.log_level}. Must be one of {valid_levels}")
            
        # Validate limits
        if self.max_checkpoints < 0:
            raise ConfigurationError(f"max_checkpoints must be non-negative, got {self.max_checkpoints}")
            
        if self.min_quality_score < 0.0 or self.min_quality_score > 100.0:
            raise ConfigurationError(f"min_quality_score must be between 0.0 and 100.0, got {self.min_quality_score}")
            
        if self.max_memory_mb <= 0:
            raise ConfigurationError(f"max_memory_mb must be positive, got {self.max_memory_mb}")
            
        if self.chunk_size is not None and self.chunk_size <= 0:
             raise ConfigurationError(f"chunk_size must be positive, got {self.chunk_size}")

    @classmethod
    def from_yaml(cls, filepath: Union[str, Path], env: str = "production") -> 'PipelineConfig':
        """
        Load configuration from YAML file
        
        Args:
            filepath: Path to YAML config file
            env: Environment to load (development/production)
        """
        path = Path(filepath)
        if not path.exists():
            raise ConfigurationError(f"Config file not found: {path}")
            
        try:
            with open(path, 'r') as f:
                data = yaml.safe_load(f)
                
            if env not in data:
                raise ConfigurationError(f"Environment '{env}' not found in config")
                
            env_config = data[env]
            
            # Extract data quality settings if present
            quality_config = data.get('data_quality', {})
            
            # Merge settings
            config_dict = {
                'log_level': env_config.get('log_level', 'INFO'),
                'log_file': env_config.get('log_file'),
                'strict_mode': env_config.get('strict_mode', False),
                'chunk_size': env_config.get('chunk_size'),
                'max_memory_mb': env_config.get('max_memory_mb', 2048),
                'enable_validation': env_config.get('enable_validation', True),
                'min_quality_score': quality_config.get('min_quality_score', 0.0),
                'max_checkpoints': env_config.get('max_checkpoints', 10)
            }
            
            return cls(**config_dict)
            
        except yaml.YAMLError as e:
            raise ConfigurationError(f"Error parsing YAML config: {e}")
        except Exception as e:
            raise ConfigurationError(f"Failed to load config: {e}")
