"""Qdrant Vector Store Service"""
from typing import List, Optional
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct
from normbase.config import settings


class QdrantService:
    """Qdrant vector database service"""
    
    def __init__(
        self,
        url: Optional[str] = None,
        collection_name: Optional[str] = None,
        vector_size: Optional[int] = None,
    ):
        self.client = QdrantClient(url=url or settings.qdrant_url)
        self.collection_name = collection_name or settings.qdrant_collection
        self.vector_size = vector_size or settings.qdrant_vector_size
        self._ensure_collection()
    
    def _ensure_collection(self):
        """Create collection if not exists, otherwise validate vector size."""
        collections = self.client.get_collections().collections
        collection_names = [c.name for c in collections]
        
        if self.collection_name not in collection_names:
            self.client.create_collection(
                collection_name=self.collection_name,
                vectors_config=VectorParams(
                    size=self.vector_size,
                    distance=Distance.COSINE
                )
            )
            return
        
        self._validate_vector_size()

    def _validate_vector_size(self):
        """Validate existing collection vector size against current settings."""
        collection_info = self.client.get_collection(collection_name=self.collection_name)
        vectors = collection_info.config.params.vectors
        actual_size: Optional[int] = None

        # Single unnamed vector config
        if hasattr(vectors, "size"):
            actual_size = vectors.size
        # Named vectors config
        elif hasattr(vectors, "values"):
            values = list(vectors.values())
            if values:
                actual_size = values[0].size

        if actual_size is None:
            raise RuntimeError(
                f"Unable to determine vector size for collection '{self.collection_name}'."
            )

        if actual_size != self.vector_size:
            raise RuntimeError(
                "Qdrant vector size mismatch for collection "
                f"'{self.collection_name}': expected {self.vector_size}, got {actual_size}. "
                "Please recreate the collection and re-vectorize norms."
            )
    
    def get_embedding(self, text: str, provider=None) -> List[float]:
        """Get embedding for text"""
        if provider:
            return provider.get_embedding(text)
        
        # Fallback: return zero vector (should use LLM provider)
        return [0.0] * self.vector_size

    def recreate_collection(self, vector_size: Optional[int] = None):
        """Drop and recreate collection with a target vector size."""
        target_size = vector_size or self.vector_size
        self.client.delete_collection(collection_name=self.collection_name)
        self.client.create_collection(
            collection_name=self.collection_name,
            vectors_config=VectorParams(
                size=target_size,
                distance=Distance.COSINE
            )
        )
    
    def search(
        self,
        query_vector: List[float],
        limit: int = 5,
        score_threshold: Optional[float] = None
    ) -> List[dict]:
        """Search similar vectors"""
        response = self.client.query_points(
            collection_name=self.collection_name,
            query=query_vector,
            limit=limit,
            score_threshold=score_threshold
        )
        results = response.points if response and response.points else []
        
        return [
            {
                "id": str(r.id),
                "score": r.score,
                "payload": r.payload
            }
            for r in results
        ]
    
    def upsert_norm(
        self,
        norm_id: str,
        text: str,
        metadata: dict,
        provider=None
    ):
        """Insert or update a norm vector"""
        vector = self.get_embedding(text, provider)
        
        self.client.upsert(
            collection_name=self.collection_name,
            points=[
                PointStruct(
                    id=norm_id,
                    vector=vector,
                    payload={
                        "text": text,
                        **metadata
                    }
                )
            ]
        )
    
    def delete_norm(self, norm_id: str):
        """Delete a norm vector"""
        self.client.delete(
            collection_name=self.collection_name,
            points_selector=[norm_id]
        )
    
    def get_norm_count(self) -> int:
        """Get total vectors count"""
        return self.client.count(
            collection_name=self.collection_name
        ).count
