from datetime import datetime, timezone
import re

from app.core.database import MongoDBClient
from langchain.prompts import PromptTemplate
from langchain.schema.runnable import RunnableSequence
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from bson import ObjectId
from app.core.config import config as Config
from qdrant_client import QdrantClient
from app.services.classifier_service import classificar_text

llm = ChatOpenAI(model="gpt-4", temperature=0.7)


def get_chats_by_user(session_id: str):
    mongodb = MongoDBClient()
    db = mongodb.getDatabase(Config.MONGO_DB)
    collection = db[Config.MONGO_COLLECTION]
    chats = collection.find({"session_id": session_id})
    return list(chats)


def get_chats_by_id(session_id: str, chat_id: str):
    mongodb = MongoDBClient()
    db = mongodb.getDatabase(Config.MONGO_DB)
    collection = db[Config.MONGO_COLLECTION]
    chat = collection.find_one({"_id": ObjectId(chat_id), "session_id": session_id})
    if chat:
        chat["_id"] = str(chat["_id"])
    return chat

def get_all_chats_service():
    mongodb = MongoDBClient()
    db = mongodb.getDatabase(Config.MONGO_DB)
    collection = db[Config.MONGO_COLLECTION]
    chats = collection.find({})
    return list(chats)

def process_chat_message_docs(session_id: str, chat_id: str, user_message: str, collection_name: str = None):
    mongodb = MongoDBClient()
    db = mongodb.getDatabase(Config.MONGO_DB)
    chat_collection = mongodb.getCollection(Config.MONGO_COLLECTION)
    registre_collection = mongodb.getCollection(Config.MONGO_REGISTRE_COLLECTION)

    if not collection_name:
        collection_name = classificar_text(user_message)

    print(f"Processant el missatge: {user_message} per a la col·lecció: {collection_name}")
    if collection_name == 'millora docent individual':
        bot_response = "Siusplau contacta amb l'oficina per a que et puguin ajudar corrrectament."
        chat_id = save_message_to_chat(
            chat_collection, session_id, chat_id, user_message, bot_response, collection_name
        )
        return chat_id, bot_response, collection_name

    if collection_name == "cap camp":
        bot_response = "No conec aquest context. Si us plau, especifica un context vàlid."
        chat_id = save_message_to_chat(
            chat_collection, session_id, chat_id, user_message, bot_response, collection_name
        )
        return chat_id, bot_response, collection_name

    if Config.ENVIRONMENT == "production":
        qdrant = QdrantClient(
            url=Config.QDRANT_URI,
            api_key=Config.QDRANT_API_KEY
        )
    else:
        qdrant = QdrantClient(
            host=Config.QDRANT_URI,
            port=6333
        )

    user_message = re.sub(r"[^\w\s']", "", user_message)
    user_message = re.sub(r"\s+", " ", user_message)

    try:
        qdrant.get_collection(collection_name)
    except Exception:
        bot_response = "No conec aquest context. Si us plau, especifica un context vàlid."
        chat_id = save_message_to_chat(
            chat_collection, session_id, chat_id, user_message, bot_response, collection_name
        )
        return chat_id, bot_response, collection_name

    if mongodb.getCollection(collection_name) is not None:
        docs_collection = mongodb.getCollection(collection_name)
        embeddings = OpenAIEmbeddings()
        query_embedding = embeddings.embed_query(user_message)
        print(f"Query embedding: {query_embedding}")
        search_results = qdrant.search(
            collection_name=collection_name,
            query_vector=query_embedding,
            limit=1,
            score_threshold=0.8

        )
    else:
        bot_response = "No conec aquest context. Si us plau, especifica un context vàlid."
        chat_id = save_message_to_chat(
            chat_collection, session_id, chat_id, user_message, bot_response, collection_name
        )
        return chat_id, bot_response, collection_name

    top_docs = []
    print(f"Resultats de la cerca: {search_results}")
    for result in search_results:
        print(f"Resultat: {result}")
        doc_id = result.payload.get("mongo_id")
        doc = docs_collection.find_one({"_id": doc_id})
        if doc:
            top_docs.append(doc)
            registre_consultes(registre_collection, doc_id, user_message, collection_name)

    if top_docs:
        combined_text = "\n\n".join([doc["resposta"] for doc in top_docs])
        bot_response = combined_text
    else:
        bot_response = "No he trobat informació rellevant per a la teva consulta. Si us plau, intenta formular la pregunta d'una altra manera"
        

    chat_id = save_message_to_chat(
        chat_collection, session_id, chat_id, user_message, bot_response, collection_name
    )

    return chat_id, bot_response, collection_name

def qdrant_search(qdrant: QdrantClient, embeddings: OpenAIEmbeddings, user_message: str, collection_name: str):
    query_embedding = embeddings.embed_query(user_message)
    search_results = qdrant.search(
        collection_name=collection_name,
        query_vector=query_embedding,
        limit=1,
        score_threshold=0.7
    )
    return search_results

def save_message_to_chat(chat_collection, session_id, chat_id, user_message, bot_response, collection_name=None):
    from datetime import datetime, timezone

    update_fields = {
        "ultima_pregunta": user_message,
        "modified": datetime.now(timezone.utc)
    }
    if collection_name:
        update_fields["context_actiu"] = collection_name

    if chat_id:
        chat = chat_collection.find_one({"_id": ObjectId(chat_id), "session_id": session_id})
        if not chat:
            raise ValueError("Xat no trobat o no pertany a l'usuari")

        chat_collection.update_one(
            {"_id": ObjectId(chat_id)},
            {
                "$push": {"messages": {"user": user_message, "bot": bot_response}},
                "$set": update_fields
            }
        )
        return chat_id
    else:
        chat_data = {
            "session_id": session_id,
            "messages": [{"user": user_message, "bot": bot_response}],
            "ultima_pregunta": user_message,
            "modified": datetime.now(timezone.utc)
        }
        if collection_name:
            chat_data["context_actiu"] = collection_name
        result = chat_collection.insert_one(chat_data)
        return str(result.inserted_id)
    

def registre_consultes(registre_collection, doc_id, user_message: str, collection_name: str):
    registre_collection.update_one(
        {"doc_id": doc_id},
        {
            "$inc": {"views": 1},
            "$set": {
                "collection": collection_name,
            },
            "$push": {
                "messages": {
                    "user_message": user_message
                }
            },
        },
        upsert=True
    )