"""
Storm Logger Implementation
Modern, configurable logging system for Storm Development
"""

import logging
import logging.config
from typing import Any

from ..config import StormLoggerConfig, get_config
from ..context_detector import ContextDetector
from .base import BaseStormLogger, create_base_logging_config, setup_logging_directories


class StormLogger(BaseStormLogger):
    """
    Storm Logger - Enterprise-grade logging with business intelligence.

    This is the main Storm Logger implementation that provides:
    - Framework-agnostic logging configuration
    - Business context detection
    - Professional formatting and console output
    - Configurable handlers and formatters
    - Performance optimization features
    """

    def __init__(
        self,
        name: str,
        config: StormLoggerConfig | None = None,
        auto_detect_context: bool = True,
    ) -> None:
        super().__init__(name, config)
        self.auto_detect_context = auto_detect_context
        self._context_detector: ContextDetector | None = None
        self._business_metrics: dict[str, Any] = {}

        # Initialize context detector if enabled
        if self.auto_detect_context and self.config.enable_context_detection:
            self._context_detector = ContextDetector()

    def _configure_handlers(self) -> None:
        """Configure log handlers based on configuration."""
        # Create log directories first
        setup_logging_directories(self.config)

        logging_config = create_base_logging_config(self.config)

        # Apply the logging configuration
        logging.config.dictConfig(logging_config)

    def _configure_formatters(self) -> None:
        """Configure log formatters based on configuration."""
        # Formatters are configured in the logging config
        pass

    def _format_message(
        self, message: str, _level: str, _exc_info: Any = None, **kwargs: Any
    ) -> str:
        """Format message with Storm enhancements."""
        # Add context information if available
        if self._context_detector and self.auto_detect_context:
            context = self._context_detector.get_context()
            kwargs["context"] = context

        # Add business metrics if enabled
        if self.config.enable_business_metrics:
            kwargs["business_metrics"] = self._business_metrics

        return message

    def debug(self, message: str, **kwargs: Any) -> None:
        """Log a debug message with Storm enhancements."""
        formatted_message = self._format_message(message, "DEBUG", **kwargs)
        super().debug(formatted_message, **kwargs)

    def info(self, message: str, **kwargs: Any) -> None:
        """Log an info message with Storm enhancements."""
        formatted_message = self._format_message(message, "INFO", **kwargs)
        super().info(formatted_message, **kwargs)

    def warning(self, message: str, **kwargs: Any) -> None:
        """Log a warning message with Storm enhancements."""
        formatted_message = self._format_message(message, "WARNING", **kwargs)
        super().warning(formatted_message, **kwargs)

    def error(self, message: str, exc_info: bool = False, **kwargs: Any) -> None:
        """Log an error message with Storm enhancements."""
        formatted_message = self._format_message(message, "ERROR", exc_info=exc_info, **kwargs)
        super().error(formatted_message, exc_info=exc_info, **kwargs)

    def critical(self, message: str, exc_info: bool = False, **kwargs: Any) -> None:
        """Log a critical message with Storm enhancements."""
        formatted_message = self._format_message(message, "CRITICAL", exc_info=exc_info, **kwargs)
        super().critical(formatted_message, exc_info=exc_info, **kwargs)

    def success(self, message: str, **kwargs: Any) -> None:
        """Log a success message with Storm business intelligence."""
        # Track success metrics
        if self.config.enable_business_metrics:
            self._business_metrics[f"success_{len(self._business_metrics)}"] = {
                "type": "success",
                "message": message,
                "timestamp": kwargs.get("timestamp"),
                "context": kwargs.get("context", "success"),
            }

        formatted_message = self._format_message(f"✅ SUCCESS: {message}", "INFO", **kwargs)
        super().info(formatted_message, **kwargs)

    def test_pass(self, test_name: str, **kwargs: Any) -> None:
        """Log a passed test with Storm enhancements."""
        # Track test success metrics
        if self.config.enable_business_metrics:
            self._business_metrics[f"test_pass_{test_name}"] = {
                "type": "test_pass",
                "test_name": test_name,
                "timestamp": kwargs.get("timestamp"),
                "context": kwargs.get("context", "testing"),
            }

        formatted_message = self._format_message(f"✅ PASS: {test_name}", "INFO", **kwargs)
        super().info(formatted_message, test_name=test_name, test_status="passed", **kwargs)

    def test_fail(self, test_name: str, error_message: str = "", **kwargs: Any) -> None:
        """Log a failed test with Storm enhancements."""
        # Track test failure metrics
        if self.config.enable_business_metrics:
            self._business_metrics[f"test_fail_{test_name}"] = {
                "type": "test_fail",
                "test_name": test_name,
                "error_message": error_message,
                "timestamp": kwargs.get("timestamp"),
                "context": kwargs.get("context", "testing"),
            }

        msg = f"❌ FAIL: {test_name}"
        if error_message:
            msg += f" - {error_message}"

        formatted_message = self._format_message(msg, "ERROR", **kwargs)
        super().error(
            formatted_message,
            test_name=test_name,
            test_status="failed",
            error_message=error_message,
            **kwargs,
        )

    def helpful_tip(self, message: str, **kwargs: Any) -> None:
        """Log a helpful development tip with Storm enhancements."""
        # Track tips for business intelligence
        if self.config.enable_business_metrics:
            self._business_metrics[f"tip_{len(self._business_metrics)}"] = {
                "type": "helpful_tip",
                "message": message,
                "timestamp": kwargs.get("timestamp"),
                "context": kwargs.get("context", "development"),
            }

        formatted_message = self._format_message(f"💡 TIP: {message}", "INFO", **kwargs)
        super().info(formatted_message, tip_type="helpful", **kwargs)

    def teaching_moment(self, message: str, **kwargs: Any) -> None:
        """Log educational content with Storm enhancements."""
        # Track educational content for business intelligence
        if self.config.enable_business_metrics:
            self._business_metrics[f"teaching_{len(self._business_metrics)}"] = {
                "type": "teaching_moment",
                "message": message,
                "timestamp": kwargs.get("timestamp"),
                "context": kwargs.get("context", "education"),
            }

        formatted_message = self._format_message(f"📚 LEARN: {message}", "INFO", **kwargs)
        super().info(formatted_message, teaching_content=True, **kwargs)

    def business_metric(
        self, metric_name: str, value: Any, threshold: Any | None = None, **kwargs: Any
    ) -> None:
        """Log a business metric with Storm intelligence."""
        self._business_metrics[metric_name] = {
            "value": value,
            "threshold": threshold,
            "timestamp": kwargs.get("timestamp"),
            "context": kwargs.get("context", "business"),
        }

        # Format business metric message
        metric_message = f"Business Metric: {metric_name} = {value}"
        if threshold is not None:
            metric_message += f" (threshold: {threshold})"

        self.info(
            metric_message,
            metric_name=metric_name,
            metric_value=value,
            metric_threshold=threshold,
            **kwargs,
        )

    def test_result(
        self, test_name: str, status: str, duration: float | None = None, **kwargs: Any
    ) -> None:
        """Log test results with business context."""
        test_message = f"Test: {test_name} - {status.upper()}"
        if duration is not None:
            test_message += f" ({duration:.2f}s)"

        log_level = self.info if status.lower() == "passed" else self.error
        log_level(
            test_message, test_name=test_name, test_status=status, test_duration=duration, **kwargs
        )

    def performance_metric(
        self, operation: str, duration: float, threshold: float | None = None, **kwargs: Any
    ) -> None:
        """Log performance metrics with threshold analysis."""
        perf_message = f"Performance: {operation} took {duration:.3f}s"

        if threshold is not None:
            if duration > threshold:
                perf_message += f" (EXCEEDED threshold: {threshold:.3f}s)"
                self.warning(
                    perf_message,
                    operation=operation,
                    duration=duration,
                    threshold=threshold,
                    performance_issue=True,
                    **kwargs,
                )
            else:
                perf_message += f" (within threshold: {threshold:.3f}s)"
                self.info(
                    perf_message,
                    operation=operation,
                    duration=duration,
                    threshold=threshold,
                    **kwargs,
                )
        else:
            self.info(perf_message, operation=operation, duration=duration, **kwargs)

    def security_event(
        self, event_type: str, message: str, severity: str = "warning", **kwargs: Any
    ) -> None:
        """Log security-related events."""
        security_message = f"Security Event [{event_type}]: {message}"

        if severity.lower() == "critical":
            self.critical(security_message, event_type=event_type, security_event=True, **kwargs)
        elif severity.lower() == "error":
            self.error(security_message, event_type=event_type, security_event=True, **kwargs)
        else:
            self.warning(security_message, event_type=event_type, security_event=True, **kwargs)

    def user_action(
        self, user_id: str, action: str, details: str | None = None, **kwargs: Any
    ) -> None:
        """Log user actions for audit and business intelligence."""
        action_message = f"User Action: {user_id} performed {action}"
        if details:
            action_message += f" - {details}"

        self.info(
            action_message, user_id=user_id, user_action=action, action_details=details, **kwargs
        )

    def get_business_metrics(self) -> dict[str, Any]:
        """Get collected business metrics."""
        return self._business_metrics.copy()

    def clear_business_metrics(self) -> None:
        """Clear collected business metrics."""
        self._business_metrics.clear()

    def set_context(self, context: dict[str, Any]) -> None:
        """Manually set context for logging."""
        if self._context_detector:
            self._context_detector.set_manual_context(context)

    def getLevel(self) -> int:
        """Return current logging level for compatibility."""
        return int(self.logger.level)

    def setLevel(self, level: int | str) -> None:
        """Set logging level."""
        self.logger.setLevel(level)


# Global logger instances cache
_logger_instances: dict[str, StormLogger] = {}


def get_storm_logger(
    name: str, config: StormLoggerConfig | None = None, auto_detect_context: bool = True
) -> StormLogger:
    """
    Get or create a Storm Logger instance.

    Args:
        name: Logger name (typically __name__)
        config: Optional configuration override
        auto_detect_context: Whether to enable automatic context detection

    Returns:
        StormLogger instance
    """
    # Use global config if none provided
    if config is None:
        config = get_config()

    # Create cache key
    cache_key = f"{name}_{id(config)}_{auto_detect_context}"

    # Return cached instance if available
    if cache_key in _logger_instances:
        return _logger_instances[cache_key]

    # Create new logger instance
    logger = StormLogger(name, config, auto_detect_context)
    _logger_instances[cache_key] = logger

    return logger


def setup_storm_logging(config: StormLoggerConfig | None = None) -> None:
    """
    Set up Storm Logger with the provided configuration.

    Args:
        config: Storm Logger configuration
    """
    if config is None:
        config = get_config()

    # Set up logging directories
    setup_logging_directories(config)

    # Configure root logger
    root_logger = get_storm_logger("storm", config)
    root_logger._configure_logger()


def configure_storm_logging(config_dict: dict[str, Any]) -> None:
    """
    Configure Storm Logger from a dictionary.

    Args:
        config_dict: Configuration dictionary
    """
    config = StormLoggerConfig.from_dict(config_dict)
    setup_storm_logging(config)


def get_logger(name: str) -> StormLogger:
    """
    Convenience function to get a Storm Logger instance.

    Args:
        name: Logger name

    Returns:
        StormLogger instance
    """
    return get_storm_logger(name)
