from datetime import datetime
import difflib
import os

class Logger:
    LEVELS = {
        "DEBUG": 10,
        "INFO": 20,
        "WARNING": 30,
        "ERROR": 40,
        "CRITICAL": 50,
    }

    COLORS = {
        "DEBUG": "\033[94m",
        "INFO": "\033[96m",
        "WARNING": "\033[93m",
        "ERROR": "\033[91m",
        "DATE": "\033[35m",
        "MESSAGE": "\033[96m",
        "RESET": "\033[0m",
    }

    def __init__(
        self,
        name: str = "root",
        min_level: str = "DEBUG",
        use_colors: bool = True,
        log_to_file: bool = False,
        log_dir: str = "logs",
        rotate_daily: bool = False
    ):
        self.name = name
        self.use_colors = use_colors
        self.log_to_file = log_to_file
        self.log_dir = log_dir
        self.rotate_daily = rotate_daily

        min_level = min_level.upper()
        if min_level not in self.LEVELS:
            raise ValueError(f"Invalid min_level: {min_level}")
        self.min_level_value = self.LEVELS[min_level]

        if self.log_to_file:
            os.makedirs(self.log_dir, exist_ok=True)
            self._set_log_file()

    # ---------- file handling ----------
    def _set_log_file(self):
        name = datetime.now().strftime("%Y-%m-%d") if self.rotate_daily else "log"
        self.log_file_path = os.path.join(self.log_dir, f"{name}.log")

    def _write_file(self, text: str):
        with open(self.log_file_path, "a", encoding="utf-8") as f:
            f.write(text + "\n")

    # ---------- main log ----------
    def log(self, level: str, message: str):
        level = level.upper()

        if level not in self.LEVELS:
            suggestion = self._suggest_level(level)
            raise ValueError(
                f'Unknown log level "{level}".'
                + (f' Did you mean "{suggestion}"?' if suggestion else "")
            )

        if self.LEVELS[level] < self.min_level_value:
            return

        now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

        # console
        if self.use_colors:
            c = self.COLORS
            print(
                f"{c['DATE']}[{now}]{c['RESET']} "
                f"{self.COLORS[level]}[{level}]{c['RESET']} "
                f"[{self.name}] "
                f"{c['MESSAGE']}{message}{c['RESET']}"
            )
        else:
            print(f"[{now}] [{level}] [{self.name}] {message}")

        # writing to a file
        if self.log_to_file:
            self._write_file(f"[{now}] [{level}] [{self.name}] {message}\n{'-' * 20}")

    def _suggest_level(self, wrong: str):
        matches = difflib.get_close_matches(
            wrong, self.LEVELS.keys(), n=1, cutoff=0.5
        )
        return matches[0] if matches else None

    # ---------- shortcuts ----------
    def debug(self, msg): self.log("DEBUG", msg)
    def info(self, msg): self.log("INFO", msg)
    def warning(self, msg): self.log("WARNING", msg)
    def error(self, msg): self.log("ERROR", msg)