import sys
import os
import numpy as np

import pytest

sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

pytestmark = pytest.mark.integration

def log(msg):
    print(msg)
    with open("test_progress.log", "a") as f:
        f.write(msg + "\n")

def test_12_embedding_generation():
    log("\nTesting 12_Embedding_Generation.ipynb logic...")
    try:
        from semantica.embeddings import EmbeddingGenerator, TextEmbedder
        
        # Test EmbeddingGenerator
        log("Initializing EmbeddingGenerator...")
        generator = EmbeddingGenerator()
        texts = [
            "Apple Inc. is a technology company.",
            "Microsoft Corporation develops software.",
            "Amazon provides cloud services."
        ]
        log("Generating embeddings...")
        embeddings = generator.generate_embeddings(texts, data_type="text")
        
        if len(embeddings) != 3:
            raise ValueError(f"Expected 3 embeddings, got {len(embeddings)}")
        
        log("EmbeddingGenerator: OK")
        
        # Test TextEmbedder
        log("Initializing TextEmbedder...")
        text_embedder = TextEmbedder()
        text = "Semantic knowledge graphs enable intelligent data processing."
        log("Embedding text...")
        embedding = text_embedder.embed_text(text)
        
        if len(embedding) == 0:
            raise ValueError("Embedding is empty")
        
        log("TextEmbedder: OK")
        
    except Exception as e:
        log(f"12_Embedding_Generation.ipynb failed: {e}")
        import traceback
        traceback.print_exc()

def test_13_vector_store_basic():
    log("\nTesting 13_Vector_Store.ipynb logic...")
    try:
        from semantica.vector_store import VectorStore
        
        # Initialize
        store = VectorStore(backend="faiss", dimension=768)
        
        # Store vectors
        vectors = [np.random.rand(768).astype('float32') for _ in range(10)]
        metadata = [{"id": i, "text": f"doc_{i}"} for i in range(10)]
        
        vector_ids = store.store_vectors(vectors, metadata=metadata)
        if len(vector_ids) != 10:
             raise ValueError(f"Expected 10 ids, got {len(vector_ids)}")
        
        # Search
        query = np.random.rand(768).astype('float32')
        results = store.search_vectors(query, k=5)
        if len(results) != 5:
             raise ValueError(f"Expected 5 results, got {len(results)}")
        
        log("VectorStore Basic: OK")
        
    except Exception as e:
        log(f"13_Vector_Store.ipynb failed: {e}")
        import traceback
        traceback.print_exc()

def test_advanced_vector_store():
    log("\nTesting Advanced_Vector_Store_and_Search.ipynb logic...")
    try:
        from semantica.vector_store import FAISSStore, HybridSearch, MetadataFilter, SearchRanker, NamespaceManager
        
        # Part 1: FAISSStore
        store = FAISSStore(dimension=768)
        index = store.create_index(index_type="hnsw", metric="L2", m=16)
        vectors = np.random.rand(100, 768).astype('float32')
        ids = [f"doc_{i}" for i in range(len(vectors))]
        # Note: API does not take index as first argument, it uses internal self.index
        store.add_vectors(vectors, ids=ids)
        
        query = np.random.rand(768).astype('float32')
        # Use search_similar which returns structured results
        results = store.search_similar(query, k=5)
        
        if len(results) != 5:
             raise ValueError(f"Expected 5 results, got {len(results)}")
        
        log("FAISSStore: OK")
        
        # Part 2: HybridSearch
        search = HybridSearch()
        # Mock data for hybrid search
        docs = [
            {"id": 0, "category": "Tech", "year": 2024},
            {"id": 1, "category": "Tech", "year": 2023},
            {"id": 2, "category": "Biz", "year": 2024}
        ]
        vecs = [np.random.rand(768).astype('float32') for _ in docs]
        meta = [{"category": d["category"], "year": d["year"]} for d in docs]
        v_ids = [f"doc_{d['id']}" for d in docs]
        
        # Filter
        filt = MetadataFilter().eq("category", "Tech").eq("year", 2024)
        
        results = search.search(query, vecs, meta, v_ids, filter=filt, k=10)
        found_ids = [r['id'] for r in results]
        if "doc_0" not in found_ids:
             log(f"Warning: doc_0 not found in results: {found_ids}")
             # Not raising error strictly if random vectors don't match well, but here we filter by metadata so it should match
        
        log("HybridSearch: OK")
        
        # Part 3: SearchRanker
        ranker = SearchRanker(strategy="reciprocal_rank_fusion")
        res1 = [{"id": "doc_1", "score": 0.9}, {"id": "doc_2", "score": 0.8}]
        res2 = [{"id": "doc_2", "score": 0.85}, {"id": "doc_3", "score": 0.7}]
        combined = ranker.rank([res1, res2])
        if len(combined) == 0:
            raise ValueError("Ranker returned empty list")
        log("SearchRanker: OK")
        
        # Part 4: NamespaceManager
        manager = NamespaceManager()
        ns_a = manager.create_namespace("ns_a", "Namespace A")
        manager.add_vector_to_namespace("doc_1", "ns_a")
        vecs_a = manager.get_namespace_vectors("ns_a")
        if len(vecs_a) == 0:
            raise ValueError("Namespace manager failed to retrieve vectors")
        log("NamespaceManager: OK")
        
    except Exception as e:
        log(f"Advanced_Vector_Store_and_Search.ipynb failed: {e}")
        import traceback
        traceback.print_exc()

if __name__ == '__main__':
    # clear log file
    with open("test_progress.log", "w") as f:
        f.write("Starting tests...\n")
        
    # test_12_embedding_generation()
    test_12_embedding_generation()
    test_13_vector_store_basic()
    test_advanced_vector_store()
