from typing import List, Dict, Any
from sqlalchemy.orm import Session
from sqlalchemy.exc import SQLAlchemyError

from app.core.vector_store.faiss_store import FaissVectorStore
from app.core.vector_store.embedder.mock import MockEmbedder
from app.db import models

class DocumentService:
    """
    Service class for managing document lifecycle, including
    adding, retrieving, and deleting documents and their vector metadata.
    """
    def __init__(self, vector_store: FaissVectorStore):
        self.vector_store = vector_store
        self.embedder = self.vector_store.embedder

    def add_document(self, db: Session, doc_data: Dict[str, Any]) -> int:
        """
        Adds a new document and its vector metadata.
        """
        try:
            document_db = models.Document(**doc_data)
            db.add(document_db)
            db.commit()
            db.refresh(document_db)

            # Determine embedding model name if needed
            embedding_model_name = "mock_embedder" if isinstance(self.embedder, MockEmbedder) else "GenAIEmbedder"

            # Pass db_session explicitly as positional argument, and document_id
            faiss_index_id = self.vector_store.add_document(
               text= document_db.text,
                document_id=document_db.id,
                db_session=db,
                embedding_model=embedding_model_name
            )

            return document_db.id

        except SQLAlchemyError:
            db.rollback()
            raise

    def get_all_documents(self, db: Session) -> List[models.Document]:
        """
        Retrieves all documents from the database.
        """
        return db.query(models.Document).order_by(models.Document.created_at.desc()).all()

    def delete_document(self, db: Session, document_id: int) -> int:
        """
        Deletes a document and its associated vector metadata from the database.
        """
        try:
            doc_to_delete = db.query(models.Document).filter(models.Document.id == document_id).first()
            if not doc_to_delete:
                return None
            
            # CRITICAL SECURITY: Delete associated vector metadata to prevent RAG 'Ghost Results'
            # 1. Get faiss IDs
            faiss_ids = [r.id for r in db.query(models.VectorMetadata).filter(models.VectorMetadata.document_id == document_id).all()]
            
            # 2. Remove from FAISS index
            if faiss_ids:
                 self.vector_store.remove_vectors(faiss_ids)
            
            # 3. Delete from DB
            db.query(models.VectorMetadata).filter(models.VectorMetadata.document_id == document_id).delete()
            
            db.delete(doc_to_delete)
            db.commit()
            return document_id
        except SQLAlchemyError as e:
            db.rollback()
            raise