import numpy as np
from langchain.prompts import PromptTemplate
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from app.core.config import config as Config
from sklearn.metrics.pairwise import cosine_similarity
from app.core.database import MongoDBClient
from bson import ObjectId

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

embedding_model = OpenAIEmbeddings()

def classificar_text(text : str):
    camps = ["digi", "rsu", "pmid", "grups","millora docent individual"]
    prompt_text = (
        "Llegeix el text següent i indica a quin d'aquests camps pertany: "
        + ", ".join(camps) + ".\n\n"
        "tenint en compte que digi vol dir projectes de digitalització, rsu de responsabilitat social universitària, pmid de projectes de millora i innovació docent i grups parlen de grups d'innovació docent, millora docent individual engloba tot allo que sigui millorar com a persona docent, és a dir, no com a projectes de millora si no com millorar com a professor\n\n"
        "Text: \"{question}\"\n"
        "Resposta només amb el nom d’un sol camp."
        "Si no correspon a cap camp, retorna 'cap camp'.\n"
    )
    prompt = PromptTemplate.from_template(prompt_text)
    chain = prompt | llm
    ai_response = chain.invoke({"question": text})
    return str(ai_response.content)

def classificar_text_context(ultima_pregunta:str, text: str, context: str):
    camps = ["digi", "rsu", "pmid", "grups", "millora docent individual"]
    prompt_text = (
        "Llegeix el text següent i indica a quin d'aquests camps pertany: "
        + ", ".join(camps) + ".\n\n"
        "tenint en compte que digi vol dir projectes de digitalització, rsu de responsabilitat social universitària i inclou temes d'inclusió sostenibilitat igualtat..., pmid de projectes de millora i innovació docent i grups parlen de grups d'innovació docent, millora docent individual engloba tot allo que sigui millorar com a persona docent, és a dir, no com a projectes de millora si no com millorar com a professor\n\n"
        "tingues en compte el context anterior i la ultima pregunta i si la question no menciona cap dels camps, la teva resposta ha de ser el context passat\n\n"
        "Context: \"{context}\"\n"
        "Pregunta anterior: \"{ultima_pregunta}\"\n"
        "Text: \"{question}\"\n"
        "Resposta només amb el nom d’un sol camp."
        "Si no correspon a cap camp, retorna el context actual."
    )
    prompt = PromptTemplate.from_template(prompt_text)
    chain = prompt | llm
    ai_response = chain.invoke({"question": text, "context": context, "ultima_pregunta": ultima_pregunta})
    return str(ai_response.content)


def obtenir_context_i_ultima_pregunta(chat_id: str):
    mongodb = MongoDBClient()
    db = mongodb.getDatabase(Config.MONGO_DB) 
    chat_collection = mongodb.getCollection(Config.MONGO_COLLECTION)

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

    context_actiu = chat.get("context_actiu", None)
    ultima_pregunta = chat.get("ultima_pregunta", None)

    return context_actiu, ultima_pregunta


def decidir_context(context_actual: str, ultima_pregunta: str, nova_pregunta: str, llindar: float = 0.7):
    if not context_actual or not ultima_pregunta:
        return classificar_text(nova_pregunta)
    context_actual = classificar_text_context(ultima_pregunta, nova_pregunta, context_actual)
    return context_actual    

def calcular_similitud(text1: str, text2: str) -> float:
    embeddings = OpenAIEmbeddings()

    emb1 = embeddings.embed_query(text1)
    emb2 = embeddings.embed_query(text2)

    emb1 = np.array(emb1).reshape(1, -1)
    emb2 = np.array(emb2).reshape(1, -1)

    similitud = cosine_similarity(emb1, emb2)[0][0]
    return similitud

    