import logging
from typing import Any, Callable, Dict, List, Optional, Type

logger = logging.getLogger("nebulascrape.plugins")


class BasePlugin:
    name: str = "base"
    priority: int = 50

    def on_pre_request(self, scraper, method: str, url: str, kwargs: dict) -> dict:
        return kwargs

    def on_post_request(self, scraper, response, kwargs: dict):
        return response

    def on_challenge_detected(self, scraper, response, intel_result) -> bool:
        return False

    def on_retry(self, scraper, attempt: int, decision) -> None:
        pass


class PluginRegistry:
    def __init__(self):
        self._plugins: List[BasePlugin] = []

    def register(self, plugin: BasePlugin):
        self._plugins.append(plugin)
        self._plugins.sort(key=lambda p: p.priority)
        logger.debug(f"[PluginRegistry] Registered plugin: {plugin.name}")

    def unregister(self, name: str):
        self._plugins = [p for p in self._plugins if p.name != name]

    def run_pre_request(self, scraper, method, url, kwargs):
        for plugin in self._plugins:
            try:
                kwargs = plugin.on_pre_request(scraper, method, url, kwargs)
            except Exception as e:
                logger.warning(f"[Plugin:{plugin.name}] on_pre_request error: {e}")
        return kwargs

    def run_post_request(self, scraper, response, kwargs):
        for plugin in self._plugins:
            try:
                response = plugin.on_post_request(scraper, response, kwargs)
            except Exception as e:
                logger.warning(f"[Plugin:{plugin.name}] on_post_request error: {e}")
        return response

    def run_challenge(self, scraper, response, intel_result) -> bool:
        handled = False
        for plugin in self._plugins:
            try:
                if plugin.on_challenge_detected(scraper, response, intel_result):
                    handled = True
            except Exception as e:
                logger.warning(f"[Plugin:{plugin.name}] on_challenge_detected error: {e}")
        return handled

    def run_retry(self, scraper, attempt, decision):
        for plugin in self._plugins:
            try:
                plugin.on_retry(scraper, attempt, decision)
            except Exception as e:
                logger.warning(f"[Plugin:{plugin.name}] on_retry error: {e}")
