"""Enhanced colored logger with structured logging support.

Provides colored output logging with JSON formatting and performance monitoring.
"""

from __future__ import annotations

import json
import logging
import os
import sys
from datetime import datetime
from typing import ClassVar, Dict

__version__ = "0.1.3"

# Windows ANSI color support
if sys.platform in {"win32", "cygwin"}:
    try:
        import ctypes

        kernel32 = ctypes.windll.kernel32  # type: ignore[attr-defined]
        kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
    except (OSError, AttributeError, ctypes.ArgumentError):
        sys.stderr.write("ANSI colors are not supported in this environment.")


class JSONFormatter(logging.Formatter):
    """JSON formatter for structured logging.

    Formats log records as JSON with additional metadata and context.
    """

    def format(self, record: logging.LogRecord) -> str:
        """Format log record as JSON.

        Args:
            record: Log record to format

        Returns
        -------
            JSON formatted log string
        """
        log_entry = {
            "timestamp": datetime.fromtimestamp(record.created).isoformat(),
            "level": record.levelname,
            "logger": record.name,
            "message": record.getMessage(),
            "module": record.module,
            "function": record.funcName,
            "line": record.lineno,
        }

        # Add exception information
        if record.exc_info and not record.exc_info:
            log_entry["exception"] = self.formatException(record.exc_info)

        # Add extra fields
        if hasattr(record, "extra_data"):
            log_entry.update(record.extra_data)

        return json.dumps(log_entry, ensure_ascii=False, separators=(",", ":"))


class ColoredFormatter(logging.Formatter):
    """Colored output formatter with enhanced formatting.

    Provides colored console output with consistent formatting.
    """

    COLORS: ClassVar[Dict[str, str]] = {
        "DEBUG": "\033[35m",
        "INFO": "\033[36m",
        "WARNING": "\033[33m",
        "ERROR": "\033[31m",
        "CRITICAL": "\033[31m\033[1m",
        "SUCCESS": "\033[32m",
        "RESET": "\033[0m",
    }

    def __init__(
        self,
        fmt: str | None = None,
        datefmt: str | None = None,
        *,
        use_colors: bool = True,
    ) -> None:
        super().__init__()
        if fmt is None:
            fmt = "%(message)s"
        self.datefmt = datefmt or "%Y-%m-%d %H:%M:%S"
        self.formats: dict[str, str] = {}
        for level, color in self.COLORS.items():
            if level == "RESET":
                continue
            if use_colors:
                self.formats[level] = f"{color}{fmt}{self.COLORS['RESET']}"
            else:
                self.formats[level] = fmt

    def format(self, record: logging.LogRecord) -> str:
        """Format log record with colors.

        Args:
            record: Log record object

        Returns
        -------
            Formatted log string with colors
        """
        log_fmt = self.formats.get(record.levelname, self.formats.get("INFO", ""))
        formatter = logging.Formatter(log_fmt, datefmt=self.datefmt)
        return formatter.format(record)


# 注册 SUCCESS 级别 (仅一次)
SUCCESS_LEVEL = logging.INFO + 5
# 使用模块级变量避免重复注册
if "VEKTOR_SUCCESS_LEVEL_REGISTERED" not in globals():
    logging.addLevelName(SUCCESS_LEVEL, "SUCCESS")
    globals()["VEKTOR_SUCCESS_LEVEL_REGISTERED"] = True


class StructuredLogger:
    """Structured logger with enhanced capabilities.

    Provides structured logging, performance monitoring, and contextual information.
    """

    DEBUG = logging.DEBUG
    INFO = logging.INFO
    SUCCESS = SUCCESS_LEVEL
    WARNING = logging.WARNING
    ERROR = logging.ERROR
    CRITICAL = logging.CRITICAL

    _instances: ClassVar[Dict[str, "StructuredLogger"]] = {}

    def __init__(self, name: str = "pytola", level: int = logging.INFO) -> None:
        self.logger = logging.getLogger(name)
        self.logger.setLevel(level)
        self._name = name
        self._level = level

        # Configure structured logging
        self._setup_structured_logging()

        # Check if we're in a test environment
        in_test_env = "PYTEST_CURRENT_TEST" in os.environ

        # Always setup handlers, but configure differently for test environment
        if not self.logger.handlers:
            self._setup_handlers()

        # In test environment, ensure propagation is enabled for capsys capture
        if in_test_env:
            self.logger.propagate = True

    def _setup_structured_logging(self) -> None:
        """Set up structured logging configuration (simplified)."""
        # Basic structured logging setup without external dependencies
        pass

    def _setup_handlers(self) -> None:
        """Set up logging handlers based on environment."""
        # Console handler with colors
        console_handler = logging.StreamHandler(sys.stdout)
        console_handler.setFormatter(ColoredFormatter(use_colors=sys.stdout.isatty()))
        self.logger.addHandler(console_handler)

        # File handler with JSON formatting
        try:
            file_handler = logging.FileHandler(f"{self._name}.log")
            file_handler.setFormatter(JSONFormatter())
            self.logger.addHandler(file_handler)
        except Exception:
            # Silently fail file logging setup
            pass

    @property
    def propagate(self):
        """Dynamic property that checks test environment on access."""
        return "PYTEST_CURRENT_TEST" in os.environ

    @propagate.setter
    def propagate(self, value):
        """Setter for propagate property (for compatibility)."""
        # We don't actually set a fixed value since it's dynamic
        pass

    def _update_propagate(self):
        """Update the propagate setting based on current environment."""
        in_test_env = "PYTEST_CURRENT_TEST" in os.environ
        self.logger.propagate = in_test_env

    def addHandler(self, handler: logging.Handler) -> None:  # noqa: N802
        """Add a handler to the underlying logger."""
        self.logger.addHandler(handler)

    def removeHandler(self, handler: logging.Handler) -> None:  # noqa: N802
        """Remove a handler from the underlying logger."""
        self.logger.removeHandler(handler)

    def isEnabledFor(self, level: int) -> bool:  # noqa: N802
        """Check if the logger is enabled for the given level."""
        return self.logger.isEnabledFor(level)

    def exception(self, message: str, *args, **kwargs) -> None:
        """记录异常级别日志."""
        self._update_propagate()
        self.logger.exception(message, *args, **kwargs)

    def debug(self, message: str) -> None:
        """记录调试级别日志."""
        self._update_propagate()
        self.logger.debug(message)

    def info(self, message: str) -> None:
        """记录信息级别日志."""
        self._update_propagate()
        self.logger.info(message)

    def success(self, message: str) -> None:
        """记录成功级别日志."""
        self._update_propagate()
        self.logger.log(SUCCESS_LEVEL, message)

    def warning(self, message: str) -> None:
        """记录警告级别日志."""
        self._update_propagate()
        self.logger.warning(message)

    def error(self, message: str) -> None:
        """记录错误级别日志."""
        self._update_propagate()
        self.logger.error(message)

    def critical(self, message: str) -> None:
        """记录严重错误级别日志."""
        self._update_propagate()
        self.logger.critical(message)

    def setLevel(self, level: int) -> None:  # noqa: N802
        """设置日志级别."""
        self.logger.setLevel(level)

    @classmethod
    def get_logger(
        cls,
        name: str = "pytola",
        level: int = logging.INFO,
    ) -> "StructuredLogger":
        """Get logger instance by name.

        Args:
            name: Logger name
            level: Logging level

        Returns
        -------
            StructuredLogger instance
        """
        if name not in cls._instances:
            cls._instances[name] = cls(name, level)
        return cls._instances[name]


def get_logger(name: str = "pytola", level: int = logging.INFO) -> "StructuredLogger":
    """Get structured logger instance.

    Args:
        name: Logger name
        level: Logging level

    Returns
    -------
        StructuredLogger instance
    """
    return StructuredLogger.get_logger(name, level)


_default = get_logger()
logger = _default
debug = _default.debug
info = _default.info
success = _default.success
warning = _default.warning
error = _default.error
critical = _default.critical
