import os
import shutil
import hashlib
from langchain_chroma import Chroma
from langchain_community.vectorstores import FAISS

# Initialisation par défaut pour éviter le NameError
HAS_QDRANT_CLIENT = False
HAS_QDRANT_NEW = False
HAS_QDRANT_OLD = False
QdrantVectorStore = None

# Vérification QdrantClient
try: 
    from qdrant_client import QdrantClient
    from qdrant_client.http import models as qdrant_models
    HAS_QDRANT_CLIENT = True
except ImportError: 
    QdrantClient = None

# Vérification du nouveau package officiel (Correction du bug "no attribute search")
try:
    from langchain_qdrant import QdrantVectorStore
    HAS_QDRANT_NEW = True
except ImportError:
    # Fallback sur l'ancien (déprécié)
    try:
        from langchain_community.vectorstores import Qdrant as QdrantVectorStore
        HAS_QDRANT_OLD = True
    except ImportError:
        pass

class VectorDBFactory:
    """Factory for local Big Data Vector Stores."""
    
    @staticmethod
    def reset(persist_directory="./db_storage", logger=None):
        if os.path.exists(persist_directory):
            try:
                shutil.rmtree(persist_directory)
                if logger: logger(f"DB folder deleted: {persist_directory}")
            except Exception as e: 
                if logger: logger(f"DB cleanup error: {e}", "error")

    @staticmethod
    def create(db_type, embedding_function, persist_directory="./db_storage", logger=None):
        db_type = db_type.lower()
        if db_type == "chroma":
            return Chroma(persist_directory=persist_directory, embedding_function=embedding_function)
        
        elif db_type == "faiss":
            try: return FAISS.load_local(persist_directory, embedding_function, allow_dangerous_deserialization=True)
            except: return None 
            
        elif db_type == "qdrant":
            if not HAS_QDRANT_CLIENT or (not HAS_QDRANT_NEW and not HAS_QDRANT_OLD): 
                if logger: logger("Qdrant missing. Install it using: pip install qdrant-client langchain-qdrant", "error")
                return None
                
            if HAS_QDRANT_OLD and not HAS_QDRANT_NEW:
                if logger: logger("WARNING: You are using the deprecated langchain-community Qdrant. This causes 'no attribute search' errors. Please run: pip install langchain-qdrant", "warning")
                
            if os.path.exists(persist_directory):
                try:
                    client = QdrantClient(path=persist_directory)
                    collections = client.get_collections().collections
                    if any(c.name == "rostaing_collection" for c in collections):
                        # Le constructeur varie légèrement entre la nouvelle et l'ancienne version
                        if HAS_QDRANT_NEW:
                            return QdrantVectorStore(
                                client=client, 
                                collection_name="rostaing_collection", 
                                embedding=embedding_function  # 'embedding' au singulier
                            )
                        else:
                            return QdrantVectorStore(
                                client=client, 
                                collection_name="rostaing_collection", 
                                embeddings=embedding_function # 'embeddings' au pluriel
                            )
                except Exception as e:
                    if logger: logger(f"Qdrant load error: {e}", "error")
                    return None
            return None
        else: raise ValueError(f"Database '{db_type}' not supported.")

    @staticmethod
    def _generate_ids(docs):
        ids = []
        for doc in docs:
            content_str = f"{doc.page_content}-{doc.metadata.get('source', '')}"
            hash_id = hashlib.md5(content_str.encode('utf-8')).hexdigest()
            ids.append(hash_id)
        return ids

    @staticmethod
    def add_docs(db_instance, docs, db_type, embedding_function, persist_directory="./db_storage", logger=None):
        if not docs: return db_instance
        db_type = db_type.lower()
        ids = VectorDBFactory._generate_ids(docs)

        if db_instance is None:
            if logger: logger(f"Initial database creation {db_type.upper()}...")
            
            if db_type == "faiss":
                db = FAISS.from_documents(docs, embedding_function)
                db.save_local(persist_directory)
                return db
                
            elif db_type == "qdrant":
                if not HAS_QDRANT_CLIENT: raise ImportError("pip install qdrant-client langchain-qdrant")
                
                # Utilisation de la méthode native from_documents (universelle et anti-crash)
                db = QdrantVectorStore.from_documents(
                    documents=docs,
                    embedding=embedding_function,
                    path=persist_directory,
                    collection_name="rostaing_collection",
                    ids=ids
                )
                return db
                
            elif db_type == "chroma":
                return Chroma.from_documents(docs, embedding_function, persist_directory=persist_directory, ids=ids)
        else:
            try:
                if db_type == "faiss": 
                    db_instance.add_documents(docs)
                    db_instance.save_local(persist_directory)
                else: 
                    # Ajout standard pour Chroma et le nouveau Qdrant
                    db_instance.add_documents(docs, ids=ids)
                return db_instance
            except Exception as e:
                if logger: logger(f"Error adding to Vector DB: {e}", "error")
                return db_instance


# ----------------------------------------------------------
# import os
# import shutil
# import hashlib
# from langchain_chroma import Chroma
# from langchain_community.vectorstores import FAISS

# # Ensure proper LangChain Qdrant integration
# try:
#     from langchain_community.vectorstores import Qdrant
#     from qdrant_client import QdrantClient
#     from qdrant_client.http import models as qdrant_models
# except ImportError:
#     Qdrant = None
#     QdrantClient = None

# class VectorDBFactory:
#     """Factory for local Big Data Vector Stores."""
    
#     @staticmethod
#     def reset(persist_directory="./db_storage", logger=None):
#         if os.path.exists(persist_directory):
#             try:
#                 shutil.rmtree(persist_directory)
#                 if logger: logger(f"DB folder deleted: {persist_directory}")
#             except Exception as e: 
#                 if logger: logger(f"DB cleanup error: {e}", "error")

#     @staticmethod
#     def create(db_type, embedding_function, persist_directory="./db_storage", logger=None):
#         db_type = db_type.lower()
#         if db_type == "chroma":
#             return Chroma(persist_directory=persist_directory, embedding_function=embedding_function)
#         elif db_type == "faiss":
#             try: return FAISS.load_local(persist_directory, embedding_function, allow_dangerous_deserialization=True)
#             except: return None 
#         elif db_type == "qdrant":
#             if not QdrantClient or not Qdrant: 
#                 if logger: logger("Qdrant missing. Install: pip install qdrant-client langchain-community", "error")
#                 return None
#             if os.path.exists(persist_directory):
#                 try:
#                     # Initialize properly returning the LangChain Qdrant object, NOT the bare client.
#                     client = QdrantClient(path=persist_directory)
#                     if any(c.name == "rostaing_collection" for c in client.get_collections().collections):
#                         return Qdrant(
#                             client=client, 
#                             collection_name="rostaing_collection", 
#                             embeddings=embedding_function
#                         )
#                 except Exception as e:
#                     if logger: logger(f"Qdrant load error: {e}", "error")
#                     return None
#             return None
#         else: raise ValueError(f"Database '{db_type}' not supported.")

#     @staticmethod
#     def _generate_ids(docs):
#         ids = []
#         for doc in docs:
#             content_str = f"{doc.page_content}-{doc.metadata.get('source', '')}"
#             hash_id = hashlib.md5(content_str.encode('utf-8')).hexdigest()
#             ids.append(hash_id)
#         return ids

#     @staticmethod
#     def add_docs(db_instance, docs, db_type, embedding_function, persist_directory="./db_storage", logger=None):
#         if not docs: return db_instance
#         db_type = db_type.lower()
#         ids = VectorDBFactory._generate_ids(docs)

#         if db_instance is None:
#             if logger: logger(f"Initial database creation {db_type.upper()}...")
#             if db_type == "faiss":
#                 db = FAISS.from_documents(docs, embedding_function)
#                 db.save_local(persist_directory)
#                 return db
#             elif db_type == "qdrant":
#                 if not QdrantClient: raise ImportError("pip install qdrant-client")
#                 client = QdrantClient(path=persist_directory)
                
#                 # Retrieve vector size dynamically
#                 vector_size = len(embedding_function.embed_query("test"))
#                 client.recreate_collection(
#                     collection_name="rostaing_collection", 
#                     vectors_config=qdrant_models.VectorParams(size=vector_size, distance=qdrant_models.Distance.COSINE)
#                 )
                
#                 db = Qdrant(client=client, collection_name="rostaing_collection", embeddings=embedding_function)
#                 db.add_documents(docs, ids=ids)
#                 return db
#             elif db_type == "chroma":
#                 return Chroma.from_documents(docs, embedding_function, persist_directory=persist_directory, ids=ids)
#         else:
#             try:
#                 if db_type == "faiss": 
#                     db_instance.add_documents(docs)
#                     db_instance.save_local(persist_directory)
#                 else: 
#                     db_instance.add_documents(docs, ids=ids)
#                 return db_instance
#             except Exception as e:
#                 if logger: logger(f"Error adding to Vector DB: {e}", "error")
#                 return db_instance