import atexit
import logging
from logging.handlers import TimedRotatingFileHandler
from pathlib import Path

LOGS_DIR = Path("logs")
LOGS_DIR.mkdir(parents=True, exist_ok=True)
LOGGING_FORMATTER = "%(asctime)s :: %(message)s"


class LogUtils:
    """Utility class for logging messages (Singleton)."""

    _instance = None

    def __new__(cls, *args, **kwargs):  # noqa: ARG003, ANN003, ANN002, ANN204
        """
        Create a new instance of the class if it doesn't already exist.

        This method is responsible for creating a singleton instance of the class.
        If the instance doesn't exist, it creates a new instance, sets up the logger,
        and registers a shutdown function. If the instance already exists, it returns
        the existing instance.

        Args:
            cls: The class object.
            *args: Variable length argument list.
            **kwargs: Arbitrary keyword arguments.

        Returns
        -------
            object: The singleton instance of the class.
        """
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance._setup_logger()  # noqa: SLF001
            atexit.register(cls._instance._shutdown_logger)  # Register shutdown function  # noqa: SLF001
        return cls._instance

    def _setup_logger(self, log_file: str = str(LOGS_DIR / "default.log")) -> logging.Logger:
        """Set up logging for the application."""
        self.logger = logging.getLogger(log_file)
        if not self.logger.handlers:  # Check if handlers already exist
            self.logger.setLevel(logging.INFO)

            file_handler = TimedRotatingFileHandler(
                filename=log_file,
                when="midnight",  # Change to "midnight" for daily rotation
                interval=1,  # Rotate every day
                backupCount=30,  # Keeps logs for 30 days
            )
            file_handler.setFormatter(logging.Formatter(LOGGING_FORMATTER))
            self.logger.addHandler(file_handler)
        return self.logger

    def log_access(self, message: str) -> None:
        """Log an access message."""
        self._setup_logger(str(LOGS_DIR / "access.log"))
        self.logger.info(message)

    def error_log(self, name: str = "", message: str = "") -> None:
        """Log an error message."""
        self._setup_logger(str(LOGS_DIR / "error.log"))
        formatted_message = f"{name}: {message}" if name else message
        self.logger.error(formatted_message)

    def debug_log(self, message: str = "") -> None:
        """Log a debug message."""
        self._setup_logger(str(LOGS_DIR / "debug.log"))
        logging.debug(message)
        self.logger.error(message)

    def stack_trace(self, message: str) -> None:
        """Log a stack trace message."""
        self._setup_logger(str(LOGS_DIR / "stack_trace.log"))
        self.logger.error(message)

    def _shutdown_logger(self) -> None:
        """Shutdown logger."""
        for handler in self.logger.handlers:
            logging.info("Shutting down logger...")
            handler.close()
            self.logger.removeHandler(handler)


CUSTOM_LOGGER = LogUtils()
