import re
import threading

_escape_codes_lock = threading.Lock()

# Cores para cada nível de log, usadas pelo colorlog
LOG_COLORS = {
    "DEBUG": "cyan",
    "INFO": "green",
    "WARNING": "yellow",
    "ERROR": "red",
    "CRITICAL": "bold_red",
    "SUCCESS": "bold_green",
    "STARTUP": "bold_blue",
    "VALIDATION": "blue",
    "DRY_RUN": "purple",
}

# Mapeamento de nomes de cores para códigos ANSI (usado pelos hints)
_NAMED_COLOR_ANSI = {
    "black": "\033[30m",
    "red": "\033[31m",
    "green": "\033[32m",
    "yellow": "\033[33m",
    "blue": "\033[34m",
    "purple": "\033[35m",
    "cyan": "\033[36m",
    "white": "\033[37m",
    "bold_black": "\033[1;30m",
    "bold_red": "\033[1;31m",
    "bold_green": "\033[1;32m",
    "bold_yellow": "\033[1;33m",
    "bold_blue": "\033[1;34m",
    "bold_purple": "\033[1;35m",
    "bold_cyan": "\033[1;36m",
    "bold_white": "\033[1;37m",
}

_HEX_PATTERN = re.compile(r'^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$')


def hex_to_ansi_fg(hex_color: str) -> str:
    """Converte uma cor HEX (#RRGGBB ou #RGB) para código ANSI 24-bit de foreground."""
    h = hex_color.lstrip('#')
    if len(h) == 3:
        h = ''.join(c * 2 for c in h)
    r, g, b = int(h[0:2], 16), int(h[2:4], 16), int(h[4:6], 16)
    return f"\033[38;2;{r};{g};{b}m"


def color_to_ansi(color: str) -> str:
    """Converte nome de cor ou código HEX para sequência ANSI (usado pelos hints)."""
    if _HEX_PATTERN.match(color):
        return hex_to_ansi_fg(color)
    return _NAMED_COLOR_ANSI.get(color, "")


def process_log_colors(log_colors: dict) -> dict:
    """
    Processa um dicionário de cores, convertendo valores HEX para o colorlog.

    Cores HEX como '#FF5733' são registradas no escape_codes do colorlog e
    substituídas por chaves compatíveis (ex: 'hex_ff5733').
    Nomes de cores normais como 'cyan' ou 'bold_red' são mantidos sem alteração.
    """
    import colorlog.escape_codes as _ce

    processed = {}
    with _escape_codes_lock:
        for level, color in log_colors.items():
            if isinstance(color, str) and _HEX_PATTERN.match(color):
                key = f"hex_{color.lstrip('#').lower()}"
                _ce.escape_codes[key] = hex_to_ansi_fg(color)
                processed[level] = key
            else:
                processed[level] = color
    return processed
