from __future__ import annotations
import logging
import os
import sys
from typing import Final

RESET_COLOR: Final[str] = "\033[0m"
LEVEL_COLORS: Final[dict[int, str]] = {
    logging.DEBUG: "\033[38;2;0;255;215m",
    logging.INFO: "\033[38;2;255;255;255m",
    logging.WARNING: "\033[38;2;255;255;0m",
    logging.ERROR: "\033[38;2;255;80;80m",
    logging.CRITICAL: "\033[48;2;180;0;0m\033[38;2;255;255;255m",
}

class ColorFormatter(logging.Formatter):
    def __init__(self, *args, use_color: bool = True, **kwargs) -> None:
        super().__init__(*args, **kwargs)
        self.use_color = use_color

    def format(self, record: logging.LogRecord) -> str:
        original_levelname = record.levelname
        if self.use_color:
            level_color = LEVEL_COLORS.get(record.levelno, "")
            if level_color:
                record.levelname = f"{level_color}{original_levelname}{RESET_COLOR}"
        try:
            return super().format(record)
        finally:
            record.levelname = original_levelname

def _supports_color(stream) -> bool:
    if os.getenv("NO_COLOR"):
        return False
    if os.getenv("FORCE_COLOR"):
        return True
    return hasattr(stream, "isatty") and stream.isatty()

def _create_console_handler(level: int, stream=None) -> logging.Handler:
    target_stream = stream or sys.stdout
    handler = logging.StreamHandler(target_stream)
    handler.setLevel(level)
    formatter = ColorFormatter(
        fmt="[%(asctime)s] [%(name)s] [%(levelname)s] %(message)s",
        datefmt="%Y-%m-%d %H:%M:%S",
        use_color=_supports_color(target_stream),
    )
    handler.setFormatter(formatter)
    return handler

def _create_file_handler(level: int, filename: str) -> logging.Handler:
    log_dir = os.path.dirname(os.path.abspath(filename))
    if log_dir and not os.path.exists(log_dir):
        os.makedirs(log_dir, exist_ok=True)

    from logging.handlers import RotatingFileHandler
    handler = RotatingFileHandler(
        filename, 
        maxBytes=10*1024*1024, 
        backupCount=5, 
        encoding="utf-8",
        delay=True 
    )
    handler.setLevel(level)
    
    formatter = logging.Formatter(
        fmt="[%(asctime)s] [%(name)s] [%(levelname)s] %(message)s",
        datefmt="%Y-%m-%d %H:%M:%S",
    )
    handler.setFormatter(formatter)
    return handler

def get_logger(
    name: str = "app",
    level: int = logging.INFO,
    *,
    stream=None,
    log_file: str | None = "logs/app.log",
) -> logging.Logger:
    logger = logging.getLogger(name)
    if logger.handlers:
        return logger
    
    requested_signature = (name, level, id(stream), log_file)
    existing_signature = getattr(logger, "_novacore_logger_signature", None)
    
    if existing_signature == requested_signature:
        return logger
    
    logger.handlers.clear()
    logger.setLevel(level)
    logger.propagate = False
    
    logger.addHandler(_create_console_handler(level, stream=stream))
    
    if log_file:
        logger.addHandler(_create_file_handler(level, log_file))
        
    logger._novacore_logger_signature = requested_signature
    return logger