"""
Storm Logger Configuration System
Modern configuration management for Storm Development logging
"""

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


class LogLevel(str, Enum):
    """Supported log levels for Storm Logger."""
    DEBUG = "DEBUG"
    INFO = "INFO"
    WARNING = "WARNING"
    ERROR = "ERROR"
    CRITICAL = "CRITICAL"


class Framework(str, Enum):
    """Supported framework integrations."""
    DJANGO = "django"
    FLASK = "flask"
    FASTAPI = "fastapi"
    STANDALONE = "standalone"


class StormTheme(str, Enum):
    """Available Storm console themes."""
    DEFAULT = "default"
    PROFESSIONAL = "professional"
    MINIMAL = "minimal"
    ENTERPRISE = "enterprise"


@dataclass
class StormLoggerConfig:
    """
    Comprehensive configuration for Storm Logger.
    
    This class provides a modern, type-safe configuration system that supports
    environment variables, default values, and validation.
    """
    
    # Core logging settings
    log_level: LogLevel = LogLevel.INFO
    log_directory: Optional[Path] = None
    max_file_size: int = 10 * 1024 * 1024  # 10MB
    backup_count: int = 5
    
    # Console settings
    enable_console: bool = True
    console_colors: bool = True
    storm_theme: StormTheme = StormTheme.DEFAULT
    
    # Business intelligence features
    enable_business_metrics: bool = True
    enable_context_detection: bool = True
    enable_professional_formatting: bool = True
    enable_roi_analysis: bool = True
    
    # Framework integration
    framework: Optional[Framework] = None
    framework_config: Dict[str, Any] = field(default_factory=dict)
    
    # Security and privacy
    sanitize_logs: bool = True
    detect_pii: bool = True
    encrypt_logs: bool = False
    
    # Performance settings
    enable_async_logging: bool = False
    batch_size: int = 100
    flush_interval: float = 5.0
    
    # File handling
    log_rotation: bool = True
    compression: bool = False
    archive_directory: Optional[Path] = None
    
    # Custom handlers and formatters
    custom_handlers: List[str] = field(default_factory=list)
    custom_formatters: List[str] = field(default_factory=list)
    
    # Environment-specific settings
    debug_mode: bool = False
    production_mode: bool = False
    
    def __post_init__(self):
        """Validate and normalize configuration after initialization."""
        # Auto-detect debug mode if not explicitly set
        if not self.production_mode and not self.debug_mode:
            self.debug_mode = os.getenv("DEBUG", "false").lower() == "true"
            self.production_mode = not self.debug_mode
        
        # Set default log directory based on environment
        if self.log_directory is None:
            if self.debug_mode:
                self.log_directory = Path.cwd() / "logs"
            else:
                self.log_directory = Path("/var/log/storm") if os.name == "posix" else Path.cwd() / "logs"
        
        # Convert string paths to Path objects
        if isinstance(self.log_directory, str):
            self.log_directory = Path(self.log_directory)
        
        if self.archive_directory and isinstance(self.archive_directory, str):
            self.archive_directory = Path(self.archive_directory)
        
        # Validate log level
        if isinstance(self.log_level, str):
            self.log_level = LogLevel(self.log_level.upper())
        
        # Auto-detect framework if not specified
        if self.framework is None:
            self.framework = self._detect_framework()
    
    def _detect_framework(self) -> Framework:
        """Automatically detect the framework being used."""
        try:
            import django
            return Framework.DJANGO
        except ImportError:
            pass
        
        try:
            import flask
            return Framework.FLASK
        except ImportError:
            pass
        
        try:
            import fastapi
            return Framework.FASTAPI
        except ImportError:
            pass
        
        return Framework.STANDALONE
    
    @classmethod
    def from_env(cls) -> "StormLoggerConfig":
        """Create configuration from environment variables."""
        return cls(
            log_level=LogLevel(os.getenv("STORM_LOG_LEVEL", "INFO").upper()),
            log_directory=Path(os.getenv("STORM_LOG_DIR", "")) if os.getenv("STORM_LOG_DIR") else None,
            max_file_size=int(os.getenv("STORM_MAX_FILE_SIZE", "10485760")),  # 10MB
            backup_count=int(os.getenv("STORM_BACKUP_COUNT", "5")),
            enable_console=os.getenv("STORM_ENABLE_CONSOLE", "true").lower() == "true",
            console_colors=os.getenv("STORM_CONSOLE_COLORS", "true").lower() == "true",
            storm_theme=StormTheme(os.getenv("STORM_THEME", "default")),
            enable_business_metrics=os.getenv("STORM_BUSINESS_METRICS", "true").lower() == "true",
            enable_context_detection=os.getenv("STORM_CONTEXT_DETECTION", "true").lower() == "true",
            enable_professional_formatting=os.getenv("STORM_PROFESSIONAL_FORMAT", "true").lower() == "true",
            sanitize_logs=os.getenv("STORM_SANITIZE_LOGS", "true").lower() == "true",
            detect_pii=os.getenv("STORM_DETECT_PII", "true").lower() == "true",
            encrypt_logs=os.getenv("STORM_ENCRYPT_LOGS", "false").lower() == "true",
            enable_async_logging=os.getenv("STORM_ASYNC_LOGGING", "false").lower() == "true",
            debug_mode=os.getenv("DEBUG", "false").lower() == "true",
            production_mode=os.getenv("STORM_PRODUCTION", "false").lower() == "true",
        )
    
    @classmethod
    def from_dict(cls, config_dict: Dict[str, Any]) -> "StormLoggerConfig":
        """Create configuration from dictionary."""
        # Filter out keys that don't exist in the dataclass
        valid_keys = {field.name for field in cls.__dataclass_fields__.values()}
        filtered_config = {k: v for k, v in config_dict.items() if k in valid_keys}
        
        return cls(**filtered_config)
    
    def to_dict(self) -> Dict[str, Any]:
        """Convert configuration to dictionary."""
        result = {}
        for field_name, field_info in self.__dataclass_fields__.items():
            value = getattr(self, field_name)
            
            # Convert Path objects to strings
            if isinstance(value, Path):
                result[field_name] = str(value)
            # Convert Enum values to their string representation
            elif isinstance(value, Enum):
                result[field_name] = value.value
            else:
                result[field_name] = value
        
        return result
    
    def get_log_handlers(self) -> List[str]:
        """Get list of enabled log handlers based on configuration."""
        handlers = []
        
        if self.enable_console:
            handlers.append("console")
        
        if self.log_directory:
            handlers.extend(["file", "error_file"])
        
        if self.debug_mode:
            handlers.append("debug_file")
        
        if self.production_mode and self.framework == Framework.DJANGO:
            handlers.extend(["mail_admins", "syslog"])
        
        return handlers
    
    def get_logging_level(self) -> int:
        """Get Python logging level from configuration."""
        level_map = {
            LogLevel.DEBUG: logging.DEBUG,
            LogLevel.INFO: logging.INFO,
            LogLevel.WARNING: logging.WARNING,
            LogLevel.ERROR: logging.ERROR,
            LogLevel.CRITICAL: logging.CRITICAL,
        }
        return level_map[self.log_level]
    
    def create_log_directories(self) -> None:
        """Create necessary log directories."""
        if self.log_directory:
            self.log_directory.mkdir(parents=True, exist_ok=True)
            
            # Create subdirectories
            (self.log_directory / "app").mkdir(exist_ok=True)
            (self.log_directory / "errors").mkdir(exist_ok=True)
            
            if self.framework == Framework.DJANGO:
                (self.log_directory / "django").mkdir(exist_ok=True)
            
            if self.archive_directory:
                self.archive_directory.mkdir(parents=True, exist_ok=True)
    
    def validate(self) -> List[str]:
        """Validate configuration and return list of errors."""
        errors = []
        
        # Validate log directory is writable
        if self.log_directory:
            try:
                self.log_directory.mkdir(parents=True, exist_ok=True)
                test_file = self.log_directory / "test_write.tmp"
                test_file.touch()
                test_file.unlink()
            except (OSError, PermissionError) as e:
                errors.append(f"Log directory not writable: {e}")
        
        # Validate file size limits
        if self.max_file_size <= 0:
            errors.append("max_file_size must be greater than 0")
        
        if self.backup_count < 0:
            errors.append("backup_count must be non-negative")
        
        # Validate batch settings for async logging
        if self.enable_async_logging:
            if self.batch_size <= 0:
                errors.append("batch_size must be greater than 0 for async logging")
            if self.flush_interval <= 0:
                errors.append("flush_interval must be greater than 0 for async logging")
        
        return errors


# Global configuration instance
_global_config: Optional[StormLoggerConfig] = None


def get_config() -> StormLoggerConfig:
    """Get the global Storm Logger configuration."""
    global _global_config
    if _global_config is None:
        _global_config = StormLoggerConfig.from_env()
    return _global_config


def set_config(config: StormLoggerConfig) -> None:
    """Set the global Storm Logger configuration."""
    global _global_config
    _global_config = config


def reset_config() -> None:
    """Reset the global configuration to default."""
    global _global_config
    _global_config = None