import logging
import sys
from pathlib import Path
import logging.config
import re


class HTTPStatusFilter(logging.Filter):
    """
    This filter inspects uvicorn.access log records. It uses record.getMessage() to retrieve
    the fully formatted log message. Then it searches for HTTP status codes and adjusts the
    record's log level based on that status:
      - 4xx: WARNING
      - 5xx: ERROR
    All other logs remain unchanged.
    """

    # A broad pattern to find any 3-digit number in the message.
    # This should capture the HTTP status code from a line like:
    # '127.0.0.1:54946 - "GET /v2/relationships HTTP/1.1" 404'
    STATUS_CODE_PATTERN = re.compile(r"\b(\d{3})\b")

    LEVEL_TO_ANSI = {
        logging.INFO: "\033[32m",  # green
        logging.WARNING: "\033[33m",  # yellow
        logging.ERROR: "\033[31m",  # red
    }
    RESET = "\033[0m"

    def filter(self, record: logging.LogRecord) -> bool:
        if record.name != "uvicorn.access":
            return True

        message = record.getMessage()
        if codes := self.STATUS_CODE_PATTERN.findall(message):
            status_code = int(codes[-1])
            if 200 <= status_code < 300:
                record.levelno = logging.INFO
                record.levelname = "INFO"
                color = self.LEVEL_TO_ANSI[logging.INFO]
            elif 400 <= status_code < 500:
                record.levelno = logging.WARNING
                record.levelname = "WARNING"
                color = self.LEVEL_TO_ANSI[logging.WARNING]
            elif 500 <= status_code < 600:
                record.levelno = logging.ERROR
                record.levelname = "ERROR"
                color = self.LEVEL_TO_ANSI[logging.ERROR]
            else:
                return True

            # Wrap the status code in ANSI codes
            colored_code = f"{color}{status_code}{self.RESET}"
            # Replace the status code in the message
            new_msg = message.replace(str(status_code), colored_code)

            # Update record.msg and clear args to avoid formatting issues
            record.msg = new_msg
            record.args = ()

        return True


def configure_logging():
    log_dir = Path.cwd() / "logs"
    log_dir.mkdir(exist_ok=True)

    log_config = {
        "version": 1,
        "disable_existing_loggers": False,
        "filters": {"http_status_filter": {"()": HTTPStatusFilter}},
        "formatters": {
            "default": {
                "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
                "datefmt": "%Y-%m-%d %H:%M:%S",
            },
            "colored": {
                "()": "colorlog.ColoredFormatter",
                "format": "%(asctime)s - %(log_color)s%(levelname)s%(reset)s - %(message)s",
                "datefmt": "%Y-%m-%d %H:%M:%S",
                "log_colors": {
                    "DEBUG": "white",
                    "INFO": "green",
                    "WARNING": "yellow",
                    "ERROR": "red",
                    "CRITICAL": "bold_red",
                },
            },
        },
        "handlers": {
            "file": {
                "class": "logging.handlers.RotatingFileHandler",
                "formatter": "colored",
                "filename": str(log_dir / "app.log"),
                "maxBytes": 10485760,  # 10MB
                "backupCount": 5,
                "filters": ["http_status_filter"],
            },
            "console": {
                "class": "logging.StreamHandler",
                "formatter": "colored",
                "stream": sys.stdout,
                "filters": ["http_status_filter"],
            },
        },
        "loggers": {
            "": {  # Root logger
                "handlers": ["console", "file"],
                "level": "INFO",
            },
            "uvicorn": {
                "handlers": ["console", "file"],
                "level": "INFO",
                "propagate": False,
            },
            "uvicorn.error": {
                "handlers": ["console", "file"],
                "level": "INFO",
                "propagate": False,
            },
            "uvicorn.access": {
                "handlers": ["console", "file"],
                "level": "INFO",
                "propagate": False,
            },
        },
    }

    logging.config.dictConfig(log_config)
    logger = logging.getLogger()
    return logger, Path(log_config["handlers"]["file"]["filename"])
