"""
Structured logging system for Mothership
"""
import os
import sys
from datetime import datetime
from typing import Optional, Any, Dict
from .types import LoggerOptions


class Colors:
    """ANSI color codes"""
    RESET = "\033[0m"
    BOLD = "\033[1m"
    DIM = "\033[2m"

    # Foreground colors
    BLACK = "\033[30m"
    RED = "\033[31m"
    GREEN = "\033[32m"
    YELLOW = "\033[33m"
    BLUE = "\033[34m"
    MAGENTA = "\033[35m"
    CYAN = "\033[36m"
    WHITE = "\033[37m"

    # Bright colors
    BRIGHT_BLACK = "\033[90m"
    BRIGHT_RED = "\033[91m"
    BRIGHT_GREEN = "\033[92m"
    BRIGHT_YELLOW = "\033[93m"
    BRIGHT_BLUE = "\033[94m"
    BRIGHT_MAGENTA = "\033[95m"
    BRIGHT_CYAN = "\033[96m"
    BRIGHT_WHITE = "\033[97m"


class Logger:
    """Structured logger with colors and context"""

    # Log levels
    DEBUG = 0
    INFO = 1
    WARN = 2
    ERROR = 3

    LEVEL_NAMES = {
        DEBUG: "DEBUG",
        INFO: "INFO",
        WARN: "WARN",
        ERROR: "ERROR"
    }

    LEVEL_COLORS = {
        DEBUG: Colors.BRIGHT_BLACK,
        INFO: Colors.BLUE,
        WARN: Colors.YELLOW,
        ERROR: Colors.RED
    }

    def __init__(
        self,
        bot_name: str,
        level: Optional[str] = None,
        prefix: Optional[str] = None,
        colors: bool = True
    ):
        """
        Initialize logger

        Args:
            bot_name: Name of the bot
            level: Log level (debug|info|warn|error)
            prefix: Optional prefix for log messages
            colors: Enable colored output
        """
        self.bot_name = bot_name
        self.prefix = prefix
        self.colors = colors and sys.stdout.isatty()

        # Get log level from env or parameter
        level_str = level or os.getenv("LOG_LEVEL", "info")
        self.level = self._parse_level(level_str)

    def _parse_level(self, level: str) -> int:
        """Parse log level string to int"""
        level_map = {
            "debug": self.DEBUG,
            "info": self.INFO,
            "warn": self.WARN,
            "error": self.ERROR
        }
        return level_map.get(level.lower(), self.INFO)

    def _format_time(self) -> str:
        """Format current time as HH:MM:SS"""
        return datetime.now().strftime("%H:%M:%S")

    def _colorize(self, text: str, color: str) -> str:
        """Apply color to text if colors enabled"""
        if self.colors:
            return f"{color}{text}{Colors.RESET}"
        return text

    def _format_prefix(self) -> str:
        """Format log prefix with bot name and optional prefix"""
        parts = [self.bot_name]
        if self.prefix:
            parts.append(self.prefix)
        return ":".join(parts)

    def _log(
        self,
        level: int,
        message: str,
        context: Optional[Dict[str, Any]] = None
    ) -> None:
        """
        Internal log method

        Args:
            level: Log level
            message: Log message
            context: Optional context dictionary
        """
        if level < self.level:
            return

        timestamp = self._colorize(self._format_time(), Colors.BRIGHT_BLACK)
        level_name = self._colorize(
            f"[{self.LEVEL_NAMES[level]}]",
            self.LEVEL_COLORS[level]
        )
        prefix = self._colorize(f"[{self._format_prefix()}]", Colors.CYAN)

        parts = [timestamp, level_name, prefix, message]

        # Add context if provided
        if context:
            context_str = " ".join(
                f"{self._colorize(k, Colors.BRIGHT_BLACK)}={v}"
                for k, v in context.items()
            )
            parts.append(context_str)

        print(" ".join(parts), file=sys.stdout if level < self.ERROR else sys.stderr)

    def debug(self, message: str, context: Optional[Dict[str, Any]] = None) -> None:
        """Log debug message"""
        self._log(self.DEBUG, message, context)

    def info(self, message: str, context: Optional[Dict[str, Any]] = None) -> None:
        """Log info message"""
        self._log(self.INFO, message, context)

    def warn(self, message: str, context: Optional[Dict[str, Any]] = None) -> None:
        """Log warning message"""
        self._log(self.WARN, message, context)

    def error(self, message: str, error: Optional[Exception] = None) -> None:
        """
        Log error message

        Args:
            message: Error message
            error: Optional exception object
        """
        context = None
        if error:
            context = {"error": str(error)}
        self._log(self.ERROR, message, context)

    def bot_start(self) -> None:
        """Log bot startup"""
        self.info(f"{self._colorize('🚀 Bot started', Colors.GREEN)}")

    def command(self, command: str, user_id: Optional[int] = None) -> None:
        """Log command received"""
        context = {"user": user_id} if user_id else None
        self.debug(f"Command received: /{command}", context)

    def message(self, text: str, user_id: Optional[int] = None) -> None:
        """Log message received"""
        context = {"user": user_id} if user_id else None
        self.debug(f"Message received: {text[:50]}", context)

    def storage(self, operation: str, key: Optional[str] = None) -> None:
        """Log storage operation"""
        context = {"key": key} if key else None
        self.debug(f"Storage {operation}", context)

    def success(self, message: str) -> None:
        """Log success message"""
        self.info(f"{self._colorize('✓', Colors.GREEN)} {message}")

    def child(self, prefix: str) -> "Logger":
        """
        Create child logger with additional prefix

        Args:
            prefix: Additional prefix

        Returns:
            New logger instance with combined prefix
        """
        combined_prefix = f"{self.prefix}:{prefix}" if self.prefix else prefix
        return Logger(
            self.bot_name,
            level=self.LEVEL_NAMES[self.level].lower(),
            prefix=combined_prefix,
            colors=self.colors
        )

    @staticmethod
    def for_bot(bot_name: str, options: Optional[LoggerOptions] = None) -> "Logger":
        """
        Create logger for bot

        Args:
            bot_name: Name of the bot
            options: Logger options

        Returns:
            Logger instance
        """
        options = options or {}
        return Logger(
            bot_name,
            level=options.get("level"),
            prefix=options.get("prefix"),
            colors=options.get("colors", True)
        )


def create_logger(bot_name: str, options: Optional[LoggerOptions] = None) -> Logger:
    """
    Create logger for bot

    Args:
        bot_name: Name of the bot
        options: Logger options

    Returns:
        Logger instance
    """
    return Logger.for_bot(bot_name, options)
