import logging
import queue
import threading
from datetime import datetime

from colorama import Fore

# Import existing VLM engine and Qdrant DB for operations
from GramAddict.core.compiler_engine import VLMCompilerEngine
from GramAddict.core.qdrant_memory import HeuristicMemoryDB

logger = logging.getLogger(__name__)


class DojoEngine:
    """
    Project Dojo: The Data Engine.
    Handles asynchronous learning from failures (Prediction Errors).
    Instead of blocking the bot when an element is not found, the bot
    offloads the snapshot to this queue. The DojoEngine recompiles the
    heuristic using a heavy VLM model in the background and updates the DB.
    "Never make a mistake twice."
    """

    _instance = None

    @classmethod
    def get_instance(cls, device=None):
        if cls._instance is None:
            if device is None:
                raise ValueError("DojoEngine must be initialized with a device first.")
            cls._instance = DojoEngine(device)
        return cls._instance

    def __init__(self, device):
        self.learning_queue = queue.Queue()
        self.compiler = VLMCompilerEngine(device)
        self.db = HeuristicMemoryDB()
        self.is_running = False
        self.worker_thread = None

    def start(self):
        if not self.is_running:
            self.is_running = True
            self.worker_thread = threading.Thread(target=self._process_queue, daemon=True)
            self.worker_thread.start()
            logger.info(
                "⛩️ [Dojo Data Engine] Background learning pipeline initialized.", extra={"color": f"{Fore.CYAN}"}
            )

    def stop(self):
        self.is_running = False
        if self.worker_thread:
            self.worker_thread.join(timeout=2.0)

    def submit_snapshot(self, heuristic_name: str, context_xml: str, intent_prompt: str):
        """
        Submits a failed UI state to the Dojo for background recompilation.
        """
        snapshot = {
            "name": heuristic_name,
            "xml": context_xml,
            "intent": intent_prompt,
            "timestamp": datetime.now().isoformat(),
        }
        self.learning_queue.put(snapshot)
        logger.info(
            f"⛩️ [Dojo] Snapshot for '{heuristic_name}' enqueued for shadow-compilation.",
            extra={"color": f"{Fore.CYAN}"},
        )

    def _process_queue(self):
        """
        The background worker loop.
        """
        while self.is_running:
            try:
                # Wait for a job
                snapshot = self.learning_queue.get(timeout=5.0)
                h_name = snapshot["name"]
                xml = snapshot["xml"]
                intent = snapshot["intent"]

                logger.info(f"⛩️ [Dojo] Processing auto-labeling job: {h_name}...", extra={"color": f"{Fore.CYAN}"})

                # Heavy compilation
                new_rule = self.compiler.generate_heuristic(intent, xml)

                if new_rule:
                    # Overwrite legacy rule in Database (Fleet update)
                    self.db.cache_heuristic(h_name, new_rule)
                    logger.info(
                        f"⛩️ [Dojo] SUCCESS! Fleet Memory updated with robust heuristic for '{h_name}'.",
                        extra={"color": f"{Fore.GREEN}"},
                    )
                else:
                    logger.warning(
                        f"⛩️ [Dojo] FAILED to compile robust heuristic for '{h_name}'.", extra={"color": f"{Fore.RED}"}
                    )

                self.learning_queue.task_done()

            except queue.Empty:
                continue
            except Exception as e:
                logger.error(f"⛩️ [Dojo] Auto-labeling crashed: {e}")
