"""
Concrete implementations of base logger interfaces.
"""

import logging
from pathlib import Path
from typing import Any

from .base_interfaces import (
    ConfigurationBuilder,
    DependencyChecker,
    DirectoryManager,
    FormatterFactory,
    LoggerFactory,
)


class DefaultLoggerFactory(LoggerFactory):
    """Default implementation using Python's logging module."""

    def get_logger(self, name: str) -> logging.Logger:
        """Get a logger instance by name."""
        return logging.getLogger(name)

    def set_level(self, logger: logging.Logger, level: int) -> None:
        """Set the logging level for a logger."""
        logger.setLevel(level)

    def get_level(self, logger: logging.Logger) -> int:
        """Get the current logging level of a logger."""
        return logger.level

    def is_enabled_for(self, logger: logging.Logger, level: int) -> bool:
        """Check if logging is enabled for a specific level."""
        return logger.isEnabledFor(level)

    def log(self, logger: logging.Logger, level: int, message: str, **kwargs: Any) -> None:
        """Log a message at a specific level."""
        # Extract special kwargs that shouldn't go into extra
        exc_info = kwargs.pop("exc_info", None)
        extra = kwargs.pop("extra", {})

        # Add remaining kwargs to extra
        for key, value in kwargs.items():
            if key not in ["exc_info", "extra"]:
                extra[key] = value

        # Log with appropriate arguments
        if exc_info is not None:
            logger.log(level, message, exc_info=exc_info, extra=extra)
        else:
            logger.log(level, message, extra=extra)


class DefaultDependencyChecker(DependencyChecker):
    """Default implementation for checking module availability."""

    def is_available(self, module_name: str) -> bool:
        """Check if a module is available for import."""
        try:
            __import__(module_name)
        except ImportError:
            return False
        else:
            return True


class DefaultFormatterFactory(FormatterFactory):
    """Default implementation for creating formatters."""

    def __init__(self, dependency_checker: DependencyChecker | None = None):
        self.dependency_checker = dependency_checker or DefaultDependencyChecker()

    def create_colored_formatter(self) -> dict[str, Any]:
        """Create a colored formatter configuration."""
        if self.dependency_checker.is_available("colorlog"):
            return {
                "()": "colorlog.ColoredFormatter",
                "format": (
                    "{log_color}[{levelname}]{reset} {asctime} | " "{cyan}{name}{reset} | {message}"
                ),
                "style": "{",
                "datefmt": "%H:%M:%S",
                "log_colors": {
                    "DEBUG": "blue",
                    "INFO": "green",
                    "WARNING": "yellow",
                    "ERROR": "red",
                    "CRITICAL": "red,bg_white",
                },
            }
        else:
            return self.create_standard_formatter()

    def create_json_formatter(self) -> dict[str, Any]:
        """Create a JSON formatter configuration."""
        if self.dependency_checker.is_available("pythonjsonlogger"):
            return {
                "()": "pythonjsonlogger.jsonlogger.JsonFormatter",
                "format": (
                    "%(asctime)s %(name)s %(levelname)s %(module)s "
                    "%(funcName)s %(lineno)d %(message)s"
                ),
                "datefmt": "%Y-%m-%d %H:%M:%S",
            }
        else:
            # Fallback to verbose formatter
            return {
                "format": (
                    "[{levelname}] {asctime} | {name} | {module}:{funcName}:{lineno} | "
                    "Process: {process:d} Thread: {thread:d} | {message}"
                ),
                "style": "{",
                "datefmt": "%Y-%m-%d %H:%M:%S",
            }

    def create_standard_formatter(self) -> dict[str, Any]:
        """Create a standard formatter configuration."""
        return {
            "format": "[{levelname}] {asctime} | {name} | {message}",
            "style": "{",
            "datefmt": "%Y-%m-%d %H:%M:%S",
        }


class DefaultConfigurationBuilder(ConfigurationBuilder):
    """Default implementation for building logging configurations."""

    def __init__(self, formatter_factory: FormatterFactory | None = None):
        self.formatter_factory = formatter_factory or DefaultFormatterFactory()

    def build_base_config(self, config: Any) -> dict[str, Any]:
        """Build base logging configuration."""
        log_dir = config.log_directory

        # Define log file paths
        app_log_file = log_dir / "app" / "storm_app.log"
        error_log_file = log_dir / "errors" / "errors.log"

        base_level = config.log_level.value

        # Build handlers dynamically based on configuration
        handlers = {
            "console": {
                "level": base_level,
                "class": "logging.StreamHandler",
                "formatter": "colored" if config.console_colors else "standard",
                "stream": "ext://sys.stdout",
            },
            "console_error": {
                "level": "ERROR",
                "class": "logging.StreamHandler",
                "formatter": "colored" if config.console_colors else "standard",
                "stream": "ext://sys.stderr",
            },
        }

        # Add file handlers only if file logging is enabled
        handler_names = ["console"]
        if config.enable_file_logging:
            handlers["app_file"] = {
                "level": "INFO",
                "class": "logging.handlers.RotatingFileHandler",
                "filename": str(app_log_file),
                "maxBytes": config.max_file_size,
                "backupCount": config.backup_count,
                "formatter": "verbose",
                "encoding": "utf-8",
            }
            handlers["error_file"] = {
                "level": "ERROR",
                "class": "logging.handlers.RotatingFileHandler",
                "filename": str(error_log_file),
                "maxBytes": config.max_file_size // 2,  # Smaller for error logs
                "backupCount": config.backup_count * 2,  # More backups for errors
                "formatter": "verbose",
                "encoding": "utf-8",
            }
            handler_names.extend(["app_file", "error_file"])

        logging_config = {
            "version": 1,
            "disable_existing_loggers": False,
            "formatters": {
                "standard": self.formatter_factory.create_standard_formatter(),
                "verbose": self.formatter_factory.create_json_formatter(),
                "colored": self.formatter_factory.create_colored_formatter(),
            },
            "filters": {},
            "handlers": handlers,
            "loggers": {
                "": {
                    "handlers": handler_names,
                    "level": base_level,
                    "propagate": False,
                },
                "storm": {
                    "handlers": handler_names,
                    "level": base_level,
                    "propagate": False,
                },
            },
        }

        # Add debug handler if in debug mode
        if config.debug_mode and config.enable_file_logging:
            self.add_debug_handler(logging_config, config)

        return logging_config

    def add_debug_handler(self, logging_config: dict[str, Any], config: Any) -> None:
        """Add debug handler to logging configuration."""
        log_dir = config.log_directory
        debug_log_file = log_dir / "app" / "debug.log"

        logging_config["handlers"]["debug_file"] = {
            "level": "DEBUG",
            "class": "logging.handlers.RotatingFileHandler",
            "filename": str(debug_log_file),
            "maxBytes": config.max_file_size * 2,  # Larger for debug logs
            "backupCount": 2,
            "formatter": "verbose",
            "encoding": "utf-8",
        }

        # Add debug handler to loggers
        for logger_config in logging_config["loggers"].values():
            if "debug_file" not in logger_config["handlers"]:
                logger_config["handlers"].append("debug_file")


class DefaultDirectoryManager(DirectoryManager):
    """Default implementation for managing directories."""

    def create_directories(self, config: Any) -> None:
        """Create necessary directories based on configuration."""
        config.create_log_directories()

    def ensure_directory_exists(self, path: Path) -> None:
        """Ensure a specific directory exists."""
        path.mkdir(parents=True, exist_ok=True)
