"""Logger module for pytola.

This module provides a simple, loguru-style logging system with colored output,
file rotation, and easy-to-use API for the pytola application.
"""

from __future__ import annotations

import contextlib
import logging
import logging.handlers
import sys
from pathlib import Path
from typing import ClassVar, Dict, Final, Optional

__all__ = ["get_logger", "logger"]

# Log file configuration
LOG_DIR: Final[Path] = Path.home() / ".pytola" / "logs"
LOG_FILE: Final[Path] = LOG_DIR / "pytola.log"
MAX_BYTES: Final[int] = 10 * 1024 * 1024  # 10MB
BACKUP_COUNT: Final[int] = 5


class _Logger:
    """A simple, loguru-style logger.

    Provides a clean, minimal API for logging with automatic console colors
    and file rotation.

    Examples
    --------
        >>> from pytola_core.logger import logger
        >>> logger.info("Hello, World!")
        >>> logger.debug("Debug message")  # Only shown if debug enabled
        >>> logger.error("Error occurred")
    """

    _instance: Optional[logging.Logger] = None

    COLORS: ClassVar[Dict[str, str]] = {
        "DEBUG": "\033[36m",  # CYAN
        "INFO": "\033[32m",  # GREEN
        "WARNING": "\033[33m",  # YELLOW
        "ERROR": "\033[31m",  # RED
        "CRITICAL": "\033[41m",  # White on Red Background
        "RESET": "\033[0m",  # RESET COLOR
    }

    @classmethod
    def setup(cls, name: str = "pytola", level: int = logging.INFO) -> logging.Logger:
        """Set up the logger with console and file handlers.

        This method should be called once at application startup.
        Subsequent calls will return the existing logger instance.

        Parameters
        ----------
        name : str
            Logger name. Defaults to "pytola"
        level : int
            Minimum log level. Defaults to INFO
            Use logger.DEBUG for more verbose output

        Returns
        -------
        logging.Logger
            Configured logger with both console and file handlers

        Examples
        --------
            >>> from pytola_core.logger import Logger
            >>> logger = Logger.setup(level=Logger.DEBUG)
        """
        if cls._instance is not None:
            return cls._instance

        # Ensure log directory exists
        with contextlib.suppress(OSError):
            LOG_DIR.mkdir(parents=True, exist_ok=True)

        class _ColoredFormatter(logging.Formatter):
            """Custom formatter that adds ANSI colors to log messages."""

            def format(self, record: logging.LogRecord) -> str:
                """Format the log record with appropriate colors."""
                # Apply color based on log level
                log_color = cls.COLORS.get(record.levelname, cls.COLORS["RESET"])

                # Format the message first
                message = super().format(record)

                # Wrap the entire message in the level color
                return f"{log_color}{message}{cls.COLORS['RESET']}"

        # Create logger
        logger = logging.getLogger(name)
        logger.setLevel(logging.DEBUG)  # Capture all levels, filter at handler

        # Console handler - shows logs >= level
        console_handler = logging.StreamHandler(sys.stdout)
        console_handler.setLevel(level)
        console_formatter = _ColoredFormatter("%(asctime)s | %(levelname)-8s | %(message)s", datefmt="%H:%M:%S")
        console_handler.setFormatter(console_formatter)

        # File handler - captures all DEBUG+ logs with rotation
        file_handler = logging.handlers.RotatingFileHandler(
            LOG_FILE, maxBytes=MAX_BYTES, backupCount=BACKUP_COUNT, encoding="utf-8"
        )
        file_handler.setLevel(logging.DEBUG)
        file_formatter = logging.Formatter(
            "%(asctime)s - %(name)s - %(levelname)s - %(message)s", datefmt="%Y-%m-%d %H:%M:%S"
        )
        file_handler.setFormatter(file_formatter)

        # Add handlers
        logger.addHandler(console_handler)
        logger.addHandler(file_handler)

        # Prevent adding handlers multiple times
        logger.propagate = False

        cls._instance = logger
        return logger

    @classmethod
    def get_logger(cls, name: str = "pytola") -> logging.Logger:
        """Get the logger instance.

        If logger hasn't been set up yet, this will set it up with default settings.
        For custom configuration, use `Logger.setup()` instead.

        Args:
            name: Logger name. Defaults to "pytola"

        Returns
        -------
            Configured logger instance
        """
        if cls._instance is None:
            return cls.setup(name)
        return cls._instance


# Pre-configured logger instance for easy import
logger: logging.Logger = _Logger.get_logger()

# Add convenience attributes to logger object (like loguru)
# These are added dynamically for easier access to log levels
setattr(logger, "DEBUG", logging.DEBUG)  # noqa: B010
setattr(logger, "INFO", logging.INFO)  # noqa: B010
setattr(logger, "WARNING", logging.WARNING)  # noqa: B010
setattr(logger, "ERROR", logging.ERROR)  # noqa: B010
setattr(logger, "CRITICAL", logging.CRITICAL)  # noqa: B010

get_logger = _Logger.get_logger
