import logging
import time
from typing import Dict, List, Optional

from GramAddict.core.qdrant_memory import QdrantBase

logger = logging.getLogger(__name__)


class PathMemory:
    """
    Qdrant-backed memory for successful navigation paths.

    Stores: goal → [step1, step2, ...] → success
    Enables instant recall for known goals.
    """

    def __init__(self, username: str = ""):
        self.username = username
        try:
            suffix = f"_{username}" if username else ""
            self._db = QdrantBase(f"goap_paths_v1{suffix}", vector_size=768)
        except Exception:
            self._db = None

    def wipe(self):
        """Wipe all learned navigation paths from Qdrant."""
        if self._db and self._db.is_connected:
            try:
                self._db.wipe_collection()
            except Exception as e:
                logger.warning(f"⚠️ [PathMemory] Could not wipe collection: {e}")

    def recall_path(self, goal: str, current_screen_type: str) -> Optional[List[Dict]]:
        """
        Recall a previously successful path for this goal from this screen type.
        Returns list of steps or None.
        """
        if not self._db or not self._db.is_connected:
            return None

        query = f"goal: {goal} | from: {current_screen_type}"
        vec = self._db._get_embedding(query)
        if not vec:
            return None

        try:
            from qdrant_client.models import FieldCondition, Filter, MatchValue

            results = self._db.client.query_points(
                collection_name=self._db.collection_name,
                query=vec,
                query_filter=Filter(
                    must=[FieldCondition(key="start_screen", match=MatchValue(value=current_screen_type))]
                ),
                limit=3,
                score_threshold=0.85,
            ).points

            for r in results:
                p = r.payload
                if p.get("success") and p.get("steps"):
                    logger.info(
                        f"🧠 [GOAP Recall] Found path for '{goal}': "
                        f"{len(p['steps'])} steps (confidence: {p.get('confidence', 0):.2f})"
                    )
                    return p["steps"]

            return None
        except Exception as e:
            logger.debug(f"GOAP recall error: {e}")
            return None

    def learn_path(self, goal: str, start_screen: str, steps: List[Dict], success: bool):
        """Store a navigation path in Qdrant."""
        if not self._db or not self._db.is_connected:
            return

        query = f"goal: {goal} | from: {start_screen}"
        vec = self._db._get_embedding(query)
        if not vec:
            return

        seed = f"{goal}|{start_screen}"
        payload = {
            "goal": goal,
            "start_screen": start_screen,
            "steps": steps,
            "step_count": len(steps),
            "success": success,
            "confidence": 0.85 if success else 0.0,
            "timestamp": time.time(),
        }

        outcome = "✅" if success else "❌"
        self._db.upsert_point(
            seed,
            payload,
            vector=vec,
            log_success=f"🧠 [GOAP Learn] {outcome} Path for '{goal}': {len(steps)} steps from {start_screen}",
        )

    def forget_path(self, goal: str, start_screen: str):
        """Remove a cached path to force re-discovery."""
        if not self._db or not self._db.is_connected:
            return

        seed = f"{goal}|{start_screen}"
        try:
            from qdrant_client import models

            point_id = self._db.generate_uuid(seed)
            self._db.client.delete(
                collection_name=self._db.collection_name, points_selector=models.PointIdsList(points=[point_id])
            )
        except Exception as e:
            logger.debug(f"Failed to forget path: {e}")
