"""
Structured logging configuration settings for the backtesting system.

This module provides centralized configuration for all logging-related settings
including debug mode, log levels, output formats, and performance monitoring.
"""

import os
from dataclasses import dataclass
from pathlib import Path
from typing import Any


@dataclass
class LoggingSettings:
    """Comprehensive logging configuration settings."""

    # Basic logging configuration
    log_level: str = "INFO"
    log_format: str = "json"  # json or text
    enable_async_logging: bool = True
    console_output: str = "stderr"  # stdout or stderr

    # File logging configuration
    enable_file_logging: bool = True
    log_file_path: str = "logs/backtesting.log"
    enable_log_rotation: bool = True
    max_log_size_mb: int = 10
    backup_count: int = 5

    # Debug mode configuration
    debug_enabled: bool = False
    verbose_modules: list[str] = None
    log_request_response: bool = False
    max_payload_length: int = 1000

    # Performance monitoring
    enable_performance_logging: bool = True
    performance_log_threshold_ms: float = 1000.0
    enable_resource_tracking: bool = True
    enable_business_metrics: bool = True

    # Async logging configuration
    async_log_queue_size: int = 10000
    async_log_flush_interval: float = 1.0

    # Sensitive data handling
    mask_sensitive_data: bool = True
    sensitive_field_patterns: list[str] = None

    # Remote logging (for future log aggregation)
    enable_remote_logging: bool = False
    remote_endpoint: str | None = None
    remote_api_key: str | None = None

    # Correlation and tracing
    enable_correlation_tracking: bool = True
    correlation_id_header: str = "X-Correlation-ID"
    enable_request_tracing: bool = True

    def __post_init__(self):
        """Initialize default values for mutable fields."""
        if self.verbose_modules is None:
            self.verbose_modules = []

        if self.sensitive_field_patterns is None:
            self.sensitive_field_patterns = [
                "password",
                "token",
                "key",
                "secret",
                "auth",
                "credential",
                "bearer",
                "session",
                "cookie",
                "api_key",
                "access_token",
                "refresh_token",
                "private",
                "confidential",
            ]

    @classmethod
    def from_env(cls) -> "LoggingSettings":
        """Create logging settings from environment variables."""
        return cls(
            log_level=os.getenv("MAVERICK_LOG_LEVEL", "INFO").upper(),
            log_format=os.getenv("MAVERICK_LOG_FORMAT", "json").lower(),
            enable_async_logging=os.getenv("MAVERICK_ASYNC_LOGGING", "true").lower()
            == "true",
            console_output=os.getenv("MAVERICK_CONSOLE_OUTPUT", "stderr").lower(),
            # File logging
            enable_file_logging=os.getenv("MAVERICK_FILE_LOGGING", "true").lower()
            == "true",
            log_file_path=os.getenv("MAVERICK_LOG_FILE", "logs/backtesting.log"),
            enable_log_rotation=os.getenv("MAVERICK_LOG_ROTATION", "true").lower()
            == "true",
            max_log_size_mb=int(os.getenv("MAVERICK_LOG_SIZE_MB", "10")),
            backup_count=int(os.getenv("MAVERICK_LOG_BACKUPS", "5")),
            # Debug configuration
            debug_enabled=os.getenv("MAVERICK_DEBUG", "false").lower() == "true",
            log_request_response=os.getenv("MAVERICK_LOG_REQUESTS", "false").lower()
            == "true",
            max_payload_length=int(os.getenv("MAVERICK_MAX_PAYLOAD", "1000")),
            # Performance monitoring
            enable_performance_logging=os.getenv(
                "MAVERICK_PERF_LOGGING", "true"
            ).lower()
            == "true",
            performance_log_threshold_ms=float(
                os.getenv("MAVERICK_PERF_THRESHOLD", "1000.0")
            ),
            enable_resource_tracking=os.getenv(
                "MAVERICK_RESOURCE_TRACKING", "true"
            ).lower()
            == "true",
            enable_business_metrics=os.getenv(
                "MAVERICK_BUSINESS_METRICS", "true"
            ).lower()
            == "true",
            # Async logging
            async_log_queue_size=int(os.getenv("MAVERICK_LOG_QUEUE_SIZE", "10000")),
            async_log_flush_interval=float(
                os.getenv("MAVERICK_LOG_FLUSH_INTERVAL", "1.0")
            ),
            # Sensitive data
            mask_sensitive_data=os.getenv("MAVERICK_MASK_SENSITIVE", "true").lower()
            == "true",
            # Remote logging
            enable_remote_logging=os.getenv("MAVERICK_REMOTE_LOGGING", "false").lower()
            == "true",
            remote_endpoint=os.getenv("MAVERICK_REMOTE_LOG_ENDPOINT"),
            remote_api_key=os.getenv("MAVERICK_REMOTE_LOG_API_KEY"),
            # Correlation and tracing
            enable_correlation_tracking=os.getenv(
                "MAVERICK_CORRELATION_TRACKING", "true"
            ).lower()
            == "true",
            correlation_id_header=os.getenv(
                "MAVERICK_CORRELATION_HEADER", "X-Correlation-ID"
            ),
            enable_request_tracing=os.getenv("MAVERICK_REQUEST_TRACING", "true").lower()
            == "true",
        )

    def to_dict(self) -> dict[str, Any]:
        """Convert settings to dictionary for serialization."""
        return {
            "log_level": self.log_level,
            "log_format": self.log_format,
            "enable_async_logging": self.enable_async_logging,
            "console_output": self.console_output,
            "enable_file_logging": self.enable_file_logging,
            "log_file_path": self.log_file_path,
            "enable_log_rotation": self.enable_log_rotation,
            "max_log_size_mb": self.max_log_size_mb,
            "backup_count": self.backup_count,
            "debug_enabled": self.debug_enabled,
            "verbose_modules": self.verbose_modules,
            "log_request_response": self.log_request_response,
            "max_payload_length": self.max_payload_length,
            "enable_performance_logging": self.enable_performance_logging,
            "performance_log_threshold_ms": self.performance_log_threshold_ms,
            "enable_resource_tracking": self.enable_resource_tracking,
            "enable_business_metrics": self.enable_business_metrics,
            "async_log_queue_size": self.async_log_queue_size,
            "async_log_flush_interval": self.async_log_flush_interval,
            "mask_sensitive_data": self.mask_sensitive_data,
            "sensitive_field_patterns": self.sensitive_field_patterns,
            "enable_remote_logging": self.enable_remote_logging,
            "remote_endpoint": self.remote_endpoint,
            "enable_correlation_tracking": self.enable_correlation_tracking,
            "correlation_id_header": self.correlation_id_header,
            "enable_request_tracing": self.enable_request_tracing,
        }

    def ensure_log_directory(self):
        """Ensure the log directory exists."""
        if self.enable_file_logging and self.log_file_path:
            log_path = Path(self.log_file_path)
            log_path.parent.mkdir(parents=True, exist_ok=True)

    def get_debug_modules(self) -> list[str]:
        """Get list of modules for debug logging."""
        if not self.debug_enabled:
            return []

        if not self.verbose_modules:
            # Default debug modules for backtesting
            return [
                "maverick_mcp.backtesting",
                "maverick_mcp.api.tools.backtesting",
                "maverick_mcp.providers",
                "maverick_mcp.data.cache",
            ]

        return self.verbose_modules

    def should_log_performance(self, duration_ms: float) -> bool:
        """Check if operation should be logged based on performance threshold."""
        if not self.enable_performance_logging:
            return False
        return duration_ms >= self.performance_log_threshold_ms

    def get_log_file_config(self) -> dict[str, Any]:
        """Get file logging configuration."""
        if not self.enable_file_logging:
            return {}

        config = {
            "filename": self.log_file_path,
            "mode": "a",
            "encoding": "utf-8",
        }

        if self.enable_log_rotation:
            config.update(
                {
                    "maxBytes": self.max_log_size_mb * 1024 * 1024,
                    "backupCount": self.backup_count,
                }
            )

        return config

    def get_performance_config(self) -> dict[str, Any]:
        """Get performance monitoring configuration."""
        return {
            "enabled": self.enable_performance_logging,
            "threshold_ms": self.performance_log_threshold_ms,
            "resource_tracking": self.enable_resource_tracking,
            "business_metrics": self.enable_business_metrics,
        }

    def get_debug_config(self) -> dict[str, Any]:
        """Get debug configuration."""
        return {
            "enabled": self.debug_enabled,
            "verbose_modules": self.get_debug_modules(),
            "log_request_response": self.log_request_response,
            "max_payload_length": self.max_payload_length,
        }


# Environment-specific configurations
class EnvironmentLogSettings:
    """Environment-specific logging configurations."""

    @staticmethod
    def development() -> LoggingSettings:
        """Development environment logging configuration."""
        return LoggingSettings(
            log_level="DEBUG",
            log_format="text",
            debug_enabled=True,
            log_request_response=True,
            enable_performance_logging=True,
            performance_log_threshold_ms=100.0,  # Lower threshold for development
            console_output="stdout",
            enable_file_logging=True,
            log_file_path="logs/dev_backtesting.log",
        )

    @staticmethod
    def testing() -> LoggingSettings:
        """Testing environment logging configuration."""
        return LoggingSettings(
            log_level="WARNING",
            log_format="text",
            debug_enabled=False,
            enable_performance_logging=False,
            enable_file_logging=False,
            console_output="stdout",
            enable_async_logging=False,  # Synchronous for tests
        )

    @staticmethod
    def production() -> LoggingSettings:
        """Production environment logging configuration."""
        return LoggingSettings(
            log_level="INFO",
            log_format="json",
            debug_enabled=False,
            log_request_response=False,
            enable_performance_logging=True,
            performance_log_threshold_ms=2000.0,  # Higher threshold for production
            console_output="stderr",
            enable_file_logging=True,
            log_file_path="/var/log/maverick/backtesting.log",
            enable_log_rotation=True,
            max_log_size_mb=50,  # Larger files in production
            backup_count=10,
            enable_remote_logging=True,  # Enable for log aggregation
        )


# Global logging settings instance
_logging_settings: LoggingSettings | None = None


def get_logging_settings() -> LoggingSettings:
    """Get global logging settings instance."""
    global _logging_settings

    if _logging_settings is None:
        environment = os.getenv("MAVERICK_ENVIRONMENT", "development").lower()

        if environment == "development":
            _logging_settings = EnvironmentLogSettings.development()
        elif environment == "testing":
            _logging_settings = EnvironmentLogSettings.testing()
        elif environment == "production":
            _logging_settings = EnvironmentLogSettings.production()
        else:
            # Default to environment variables
            _logging_settings = LoggingSettings.from_env()

        # Override with any environment variables
        env_overrides = LoggingSettings.from_env()
        for key, value in env_overrides.to_dict().items():
            if value is not None and value != getattr(LoggingSettings(), key):
                setattr(_logging_settings, key, value)

        # Ensure log directory exists
        _logging_settings.ensure_log_directory()

    return _logging_settings


def configure_logging_for_environment(environment: str) -> LoggingSettings:
    """Configure logging for specific environment."""
    global _logging_settings

    if environment.lower() == "development":
        _logging_settings = EnvironmentLogSettings.development()
    elif environment.lower() == "testing":
        _logging_settings = EnvironmentLogSettings.testing()
    elif environment.lower() == "production":
        _logging_settings = EnvironmentLogSettings.production()
    else:
        raise ValueError(f"Unknown environment: {environment}")

    _logging_settings.ensure_log_directory()
    return _logging_settings


# Logging configuration validation
def validate_logging_settings(settings: LoggingSettings) -> list[str]:
    """Validate logging settings and return list of warnings/errors."""
    warnings = []

    # Validate log level
    valid_levels = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
    if settings.log_level not in valid_levels:
        warnings.append(f"Invalid log level '{settings.log_level}', using INFO")

    # Validate log format
    valid_formats = ["json", "text"]
    if settings.log_format not in valid_formats:
        warnings.append(f"Invalid log format '{settings.log_format}', using json")

    # Validate console output
    valid_outputs = ["stdout", "stderr"]
    if settings.console_output not in valid_outputs:
        warnings.append(
            f"Invalid console output '{settings.console_output}', using stderr"
        )

    # Validate file logging
    if settings.enable_file_logging:
        try:
            log_path = Path(settings.log_file_path)
            log_path.parent.mkdir(parents=True, exist_ok=True)
        except Exception as e:
            warnings.append(f"Cannot create log directory: {e}")

    # Validate performance settings
    if settings.performance_log_threshold_ms < 0:
        warnings.append("Performance threshold cannot be negative, using 1000ms")

    # Validate async settings
    if settings.async_log_queue_size < 100:
        warnings.append("Async log queue size too small, using 1000")

    return warnings
