import numpy as np

class SemanticCache:
    def __init__(self):
        # Stores tuples of (embedding, response)
        self.cache = []

    def store_cache(self, prompt_embedding, response):
        """Stores a prompt embedding and its corresponding response."""
        embedding_array = np.array(prompt_embedding)
        self.cache.append((embedding_array, response))

    def check_cache(self, prompt_embedding, threshold=0.9):
        """
        Checks if a similar prompt exists in the cache based on cosine similarity.
        Returns the cached response if a match is found above the threshold, otherwise None.
        """
        if not self.cache:
            return None
            
        target_embedding = np.array(prompt_embedding)
        target_norm = np.linalg.norm(target_embedding)
        
        if target_norm == 0:
            return None

        best_match_score = -1.0
        best_response = None

        for cached_embedding, response in self.cache:
            cached_norm = np.linalg.norm(cached_embedding)
            if cached_norm == 0:
                continue
                
            similarity = np.dot(target_embedding, cached_embedding) / (target_norm * cached_norm)
            
            if similarity > best_match_score:
                best_match_score = similarity
                best_response = response

        if best_match_score >= threshold:
            return best_response

        return None
