import importlib
from contextlib import contextmanager
from functools import wraps
from pathlib import Path
from typing import Dict, List, Type

import typer
from rich.console import Console

from utils.config import PatchTemplate
from utils.tools import PATCHES


class PatcherError(Exception):
    """Базовое исключение патчера"""

    pass


class ConfigError(PatcherError):
    """Ошибка конфигурации"""

    pass


class BuildError(PatcherError):
    """Ошибка сборки"""

    pass


def handle_errors(func):
    """Декоратор для обработки ошибок CLI"""

    @wraps(func)
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except PatcherError as e:
            Console().print(f"[red]Ошибка: {e}")
            raise typer.Exit(1)
        except KeyboardInterrupt:
            Console().print("\n[yellow]Прервано пользователем")
            raise typer.Exit(130)

    return wrapper


class PatchManager:
    """Менеджер для работы с патчами"""

    def __init__(self, console: Console, patches_dir: Path = PATCHES):
        self.console = console
        self.patches_dir = patches_dir

    def discover_patches(self, include_todo: bool = False) -> List[str]:
        """Находит все доступные патчи"""
        patches = []
        for f in self.patches_dir.glob("*.py"):
            if f.name == "__init__.py":
                continue
            if f.name.startswith("todo_") and not include_todo:
                continue
            patches.append(f.stem)
        return patches

    def discover_all(self) -> Dict[str, List[str]]:
        """Находит все патчи, разделяя на готовые и в разработке"""
        ready = []
        todo = []

        for f in self.patches_dir.glob("*.py"):
            if f.name == "__init__.py":
                continue
            if f.name.startswith("todo_"):
                todo.append(f.stem)
            else:
                ready.append(f.stem)

        return {"ready": ready, "todo": todo}

    def load_patch_module(self, name: str) -> type:
        """Загружает модуль патча"""
        module = importlib.import_module(f"patches.{name}")
        return module

    def load_patch_class(self, name: str) -> type:
        """Загружает класс патча"""
        module = importlib.import_module(f"patches.{name}")
        return module.Patch

    def load_patch(self, name: str) -> PatchTemplate:
        """Загружает экземпляр патча"""
        module = importlib.import_module(f"patches.{name}")
        return module.Patch(name=name, console=self.console)

    def load_enabled_patches(self) -> List[PatchTemplate]:
        """Загружает все включённые патчи, отсортированные по приоритету"""
        patches = []
        for name in self.discover_patches():
            patch = self.load_patch(name)
            if patch.enabled:
                patches.append(patch)
            else:
                self.console.print(f"[dim]≫ Пропускаем {name}[/dim]")

        return sorted(patches, key=lambda p: p.priority, reverse=True)
