import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from typing import List
from datetime import datetime

# Import actual models and base
from app.db.models import Base, Document, VectorMetadata
from app.core.retrievers.faiss_db_retriever import FaissDBRetriever


# --- Mock FaissVectorStore ---
class MockFaissVectorStore:
    def __init__(self):
        self._index = {}

    def add_document_to_index(self, text: str) -> int:
        new_id = len(self._index)
        self._index[new_id] = text
        return new_id

    def search_similar_documents(self, query_text: str, k: int = 1, db_session=None, prefilter_tags=None) -> List[int]:
        # Always return vector ID 0 for test simplicity
        return [0]


# --- Database setup ---
SQLALCHEMY_DATABASE_URL = "sqlite:///./data/test.db"
engine = create_engine(
    SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)


@pytest.fixture(scope="function")
def db_session():
    """Provides a clean database session for each test."""
    Base.metadata.create_all(bind=engine)
    db = TestingSessionLocal()
    try:
        yield db
    finally:
        db.close()
        Base.metadata.drop_all(bind=engine)


@pytest.fixture(scope="function")
def faiss_store():
    """Provides a mock FaissVectorStore for each test."""
    return MockFaissVectorStore()


# --- Tests ---
def test_retrieve_context_successful(db_session, faiss_store):
    # Step 1: Create a document
    doc = Document(
        id=123, # FAISS index is stored in `document_id`
        title="Sample Title",
        text="The quick brown fox jumps over the lazy dog.",
        source_url="",
        author="",
        status="ready",
        created_at=datetime(2023, 1, 1, 0, 0, 0),  # ✅ FIXED
        user_id="test_user"
    )
    db_session.add(doc)
    db_session.commit()

    # Step 2: Create VectorMetadata with id matching FAISS ID returned
    vector_metadata = VectorMetadata(
        id=0,  
        document_id=123, # FAISS index is stored in `document_id`
        embedding_model="mock"
    )
    db_session.add(vector_metadata)
    db_session.commit()

    # Step 3: Use retriever
    retriever = FaissDBRetriever(vector_store=faiss_store)
    faiss_store.search_similar_documents = lambda query_text, k, db_session=None, prefilter_tags=None: [123]

    retrieved_context = retriever.retrieve_context(query="query for fox", db=db_session)

    # Step 4: Assertions
    assert len(retrieved_context) == 1
    assert retrieved_context[0] == "The quick brown fox jumps over the lazy dog."


def test_retrieve_context_no_match(db_session, faiss_store):
    retriever = FaissDBRetriever(vector_store=faiss_store)

    # Override to return empty list
    faiss_store.search_similar_documents = lambda query_text, k, db_session=None, prefilter_tags=None: []

    retrieved_context = retriever.retrieve_context(query="no match", db=db_session)
    assert retrieved_context == []
