import numpy as np
from typing import List, Dict, Any, Callable

def default_embedding_function(text: str) -> np.ndarray:
    """
    A simple deterministic dummy embedding function for demonstration.
    In production, this should call a real embedding model.
    """
    # Create a simple hash-like embedding
    seed = sum(ord(c) * (i + 1) for i, c in enumerate(text))
    np.random.seed(seed % 4294967295)  # Ensure seed is within valid range
    return np.random.rand(128)

def cosine_similarity(a: np.ndarray, b: np.ndarray) -> float:
    norm_a = np.linalg.norm(a)
    norm_b = np.linalg.norm(b)
    if norm_a == 0 or norm_b == 0:
        return 0.0
    return float(np.dot(a, b) / (norm_a * norm_b))

class VectorStore:
    def __init__(self, embedding_function: Callable[[str], np.ndarray] = None):
        if embedding_function is None:
            embedding_function = default_embedding_function
        self.embedding_function = embedding_function
        self.documents: List[Dict[str, Any]] = []
        self.embeddings: List[np.ndarray] = []

    def add_documents(self, docs: List[Dict[str, Any]]) -> None:
        """
        Adds a list of documents to the vector store.
        Each document should be a dict with at least a 'content' key.
        """
        for doc in docs:
            content = doc.get("content", "")
            if not content:
                continue
            emb = self.embedding_function(content)
            self.documents.append(doc)
            self.embeddings.append(emb)

    def search(self, query: str, top_k: int = 5) -> List[Dict[str, Any]]:
        """
        Searches for the most similar documents to the query.
        """
        if not self.documents:
            return []
            
        query_emb = self.embedding_function(query)
        similarities = []
        for i, emb in enumerate(self.embeddings):
            sim = cosine_similarity(query_emb, emb)
            similarities.append((sim, i))
            
        # Sort by similarity descending
        similarities.sort(key=lambda x: x[0], reverse=True)
        
        results = []
        for sim, idx in similarities[:top_k]:
            res = dict(self.documents[idx])
            res["score"] = float(sim)
            results.append(res)
            
        return results
