import logging
import time
from typing import Optional

from colorama import Fore
from qdrant_client.models import FieldCondition, Filter, MatchValue

from GramAddict.core.qdrant_memory import QdrantBase

logger = logging.getLogger(__name__)


class SwarmProtocol(QdrantBase):
    """
    Decentralized Markov state-channel for P2P knowledge sharing.

    Manages 'Pheromones' (successful UI transitions and interactions)
    and 'BannedPaths' (failed attempts) across bot sessions.

    This creates a Fleet Learning effect: every session learns from
    every previous session's successes and failures.
    """

    def __init__(self, username: str):
        self.username = username
        super().__init__(collection_name="gramaddict_swarm_pheromones", vector_size=4)

    def emit_pheromone(self, path_hash: str, outcome: str):
        """
        Broadcasting a successful UI transition or interaction to the fleet memory.
        Future sessions can use this to avoid failed paths and repeat successful ones.
        """
        if not self.is_connected or not self.client:
            return

        try:
            self.upsert_point(
                seed_string=f"{path_hash}_{outcome}",
                vector=[1.0, 0.0, 0.0, 0.0],  # Dummy vector
                payload={
                    "path_hash": path_hash,
                    "outcome": outcome,
                    "username": self.username,
                    "timestamp": time.time(),
                    "count": 1,
                },
                log_success=f"🌐 [Swarm] ⚡ Pheromone emitted: {path_hash[:16]} → {outcome}",
            )
        except Exception as e:
            logger.debug(f"[Swarm] Pheromone emit failed: {e}")

    def query_consensus(self, path_hash: str) -> Optional[str]:
        """
        Queries the swarm for historical outcomes of a specific path.
        Returns the most recent outcome or None.
        """
        if not self.is_connected or not self.client:
            return None

        try:
            points, _ = self.client.scroll(
                collection_name=self.collection_name,
                scroll_filter=Filter(must=[FieldCondition(key="path_hash", match=MatchValue(value=path_hash))]),
                limit=1,
                with_payload=True,
            )

            if points:
                outcome = points[0].payload.get("outcome")
                logger.info(f"🌐 [Swarm] Consensus for {path_hash[:16]}: {outcome}", extra={"color": f"{Fore.CYAN}"})
                return outcome
        except Exception as e:
            logger.debug(f"[Swarm] Consensus query failed: {e}")

        return None

    def sync_banned_paths(self, banned_paths_db):
        """
        Pull globally banned paths from the swarm into local BannedPathsDB.
        Ensures new sessions immediately know about failed paths.
        """
        if not self.is_connected or not self.client:
            return

        try:
            points, _ = self.client.scroll(
                collection_name=self.collection_name,
                scroll_filter=Filter(must=[FieldCondition(key="outcome", match=MatchValue(value="banned"))]),
                limit=100,
                with_payload=True,
            )

            synced = 0
            for pt in points:
                payload = pt.payload or {}
                path = payload.get("path_hash", "")
                if path and banned_paths_db:
                    banned_paths_db.ban(path, "swarm_synced", reason="Synced from fleet memory")
                    synced += 1

            if synced > 0:
                logger.info(
                    f"🌐 [Swarm] Synced {synced} banned paths from fleet memory.", extra={"color": f"{Fore.CYAN}"}
                )
        except Exception as e:
            logger.debug(f"[Swarm] Banned path sync failed: {e}")
