import logging
import logging.handlers
import platform
import os
from typing import List, Optional

# Дополнительная проверка для ОС Windows
if platform.system() == "Windows":
    os.system('color')

class CustomFormatter(logging.Formatter):
    COLORS = {        
        "black" : "\x1b[30m",    
        "red" : "\x1b[31m",    
        "green" : "\x1b[32m",    
        "yellow" : "\x1b[33m",    
        "blue" : "\x1b[34m",    
        "magenta" : "\x1b[35m",    
        "cyan" : "\x1b[36m",    
        "white" : "\x1b[37m",
        "reset": "\x1b[0m"    
    }
    
    FORMATS = {
        logging.DEBUG: COLORS["green"] + "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)" + COLORS["reset"],
        logging.INFO: COLORS["magenta"] + "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)" + COLORS["reset"],
        logging.WARNING: COLORS["yellow"] + "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)" + COLORS["reset"],
        logging.ERROR: COLORS["red"] + "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)" + COLORS["reset"],
        logging.CRITICAL: COLORS["cyan"] + "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)" + COLORS["reset"]
    }
    
    def __init__(self):
        super().__init__(fmt="%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)")
    
    def format(self, record: logging.LogRecord) -> str:
        log_fmt = self.FORMATS.get(record.levelno)
        if log_fmt:
            self._style._fmt = log_fmt
        return super().format(record)
    
class MultiLevelFilter(logging.Filter):
    def __init__(self, levels: List[int]):
        self.levels = levels

    def filter(self, record: logging.LogRecord) -> bool:
        return record.levelno in self.levels
    
class LevelFilter(logging.Filter):
    def __init__(self, level: int):
        self.level = level
            
    def filter(self, record: logging.LogRecord) -> bool:
        return record.levelno == self.level

class LoggerManager:
    LEVEL_MAPPING = {
        'DEBUG': logging.DEBUG,
        'INFO': logging.INFO,
        'WARNING': logging.WARNING,
        'ERROR': logging.ERROR,
        'CRITICAL': logging.CRITICAL
    }
    
    def __init__(self, name: str, level: int = logging.DEBUG, log_to_file: bool = False, file_name: str = 'app.log'):
        if not isinstance(name, str) or not name.strip():
            print(f"Некорректное имя логгера: '{name}'. Устанавливается имя по умолчанию 'DefaultLogger'.")
            name = "DefaultLogger"
        self.logger = logging.getLogger(name)
        self.logger.setLevel(level)
        self.console_handler: Optional[logging.StreamHandler] = None
        self.file_handler: Optional[logging.FileHandler] = None
        self.log_filter: Optional[logging.Filter] = None
        self.setup_console_handler(level)
        if log_to_file:
            self.setup_file_handler(level, file_name)
    
    def setup_console_handler(self, level: int):
        """Настройка консольного обработчика и форматтера"""
        self.console_handler = logging.StreamHandler()
        self.console_handler.setLevel(level)
        self.console_handler.setFormatter(CustomFormatter())
        self.logger.addHandler(self.console_handler)
    
    def setup_file_handler(self, level: int, file_name: str):
        """Настройка обработчика с ротацией файлов"""
        try:
            self.file_handler = logging.handlers.RotatingFileHandler(
                file_name,
                maxBytes=1024*1024,  # Максимальный размер файла (1MB)
                #maxBytes=1024,  # Максимальный размер файла (1кб)
                backupCount=5  # Количество ротируемых файлов
            )
            self.file_handler.setLevel(level)
            file_formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)")
            self.file_handler.setFormatter(file_formatter)
            self.logger.addHandler(self.file_handler)
        except Exception as e:
            self.logger.error(f"Ошибка при настройке файлового логгера с ротацией: {e}")
            raise
        
    def enable_console_logging(self):
        """Включение логирования в консоль"""
        if self.console_handler:
            self.console_handler.setLevel(self.logger.level)
            self.logger.info("Логирование в консоль включено")

    def disable_console_logging(self):
        """Отключение логирования в консоль"""
        if self.console_handler:
            self.console_handler.setLevel(logging.CRITICAL + 1)  # Уровень выше CRITICAL, чтобы игнорировать все сообщения
            self.logger.info("Логирование в консоль отключено")
    
    def enable_logging(self):
        """Включение логирования"""
        self.logger.disabled = False
        self.logger.info("Логирование включено")

    def disable_logging(self):
        """Отключение логирования"""
        self.logger.disabled = True
        self.logger.info("Логирование отключено")

    def enable_file_logging(self, file_name: str = 'app.log', log_dir: str = 'logs'):
        if not os.path.exists(log_dir):
            os.makedirs(log_dir)
    
        log_path = os.path.join(log_dir, file_name)
    
        if self.file_handler:
            self.logger.removeHandler(self.file_handler)
            self.file_handler.close()

        self.setup_file_handler(self.logger.level, log_path)
        self.logger.info(f"Логирование в файл '{log_path}' включено")

    def disable_file_logging(self):
        """Отключение логирования в файл"""
        if self.file_handler:
            self.logger.removeHandler(self.file_handler)
            self.file_handler.close()
            self.file_handler = None
        self.logger.info("Логирование в файл отключено")

    def set_level(self, level: str):
        """Установка уровня логирования"""
        if level in self.LEVEL_MAPPING:
            self.logger.setLevel(self.LEVEL_MAPPING[level])
            if self.console_handler:
                self.console_handler.setLevel(self.LEVEL_MAPPING[level])
            if self.file_handler:
                self.file_handler.setLevel(self.LEVEL_MAPPING[level])
            self.logger.info(f"Уровень логирования установлен на {level}")
        else:
            self.logger.error(f"Некорректный уровень логирования: {level}. Используйте один из: {list(self.LEVEL_MAPPING.keys())}")
    
    def set_filter(self, level: str):
        """Установка фильтра для логирования"""
        if level in self.LEVEL_MAPPING:
            self.clear_filter()
            self.log_filter = LevelFilter(self.LEVEL_MAPPING[level])
            self.logger.addFilter(self.log_filter)
            self.logger.info(f"Фильтр уровня логирования установлен на {level}")
        else:
            self.logger.error(f"Некорректный уровень фильтра: {level}. Используйте один из: {list(self.LEVEL_MAPPING.keys())}")
            
    def set_filter_list(self, levels: List[str]):
        """Установка списка фильтров для логирования"""
        if not levels:
            self.logger.error("Список уровней фильтра не должен быть пустым.")
            return

        valid_levels = [self.LEVEL_MAPPING[level] for level in levels if level in self.LEVEL_MAPPING]
        
        if not valid_levels:
            self.logger.error(f"Некорректные уровни фильтра: {levels}. Используйте один из: {list(self.LEVEL_MAPPING.keys())}")
            return
        
        self.clear_filter()
        self.log_filter = MultiLevelFilter(valid_levels)
        self.logger.addFilter(self.log_filter)
        self.logger.info(f"Фильтр уровней логирования установлен на {levels}")
        
    def reset_level(self):
        """Сброс уровня логирования до уровня DEBUG"""
        self.set_level('DEBUG')
    
    def clear_filter(self):
        """Очистка установленного фильтра"""
        if self.log_filter:
            self.logger.removeFilter(self.log_filter)
            self.log_filter = None
            self.logger.info("Фильтр логирования очищен")

if __name__ == "__main__":
    import time
    import datetime
    
    logger_manager = LoggerManager("TestLogger")
    #logger_manager.enable_console_logging() # Включение логирования в консоль
    #logger_manager.disable_console_logging() # Отключение логирования в консоль
    #logger_manager.disable_logging()  # Отключение логирования
    #logger_manager.enable_logging()   # Включение логирования
    #logger_manager.set_level('INFO')  # Установка уровня логирования на INFO
    #logger_manager.set_filter_list(['DEBUG' ,'WARNING', 'ERROR' ]) # Установка списка фильтров для логирования
    #logger_manager.set_filter('INFO')  # Фильтрация сообщений только уровня INFO
    #logger_manager.clear_filter()  # Очистка установленного фильтра
    #logger_manager.reset_level()  # Сброс уровня логирования до уровня DEBUG
    
    
    for i in range(6):
        # Включение и отключение логирования в файл
        logger_manager.enable_file_logging(f"{datetime.datetime.now().strftime('%Y-%m-%d %H-%M'),i}.log")
        #logger_manager.disable_file_logging()

        # Логирование сообщений
        logger = logger_manager.logger
        logger.debug(f"debug message {i}")  
        logger.info(f"info message {i}")
        logger.warning(f"warning message {i}")  
        logger.error(f"error message {i}")  
        logger.critical(f"critical message {i}")  
        time.sleep(1)