from langchain_community.tools.tavily_search import TavilySearchResults
from typing import Annotated
from typing_extensions import TypedDict
from langgraph.graph.message import add_messages
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
from langgraph.prebuilt import create_react_agent
from langchain_core.prompts import ChatPromptTemplate
from langgraph.checkpoint.memory import MemorySaver
from langchain_tools.agent_tools import (
    redact_email, list_calendar_events,
    create_calendar_event,
    get_company_info,
    get_current_date_and_time
)
from langchain_community.tools.gmail.utils import (
    build_resource_service,
    get_gmail_credentials,
)
from langchain_community.agent_toolkits import GmailToolkit


load_dotenv()


# Inicialiamos un LLM de OpenaIA
llm = ChatOpenAI(
    model="gpt-4o-mini",
    temperature=0.9
)

toolkit = GmailToolkit()

# Can review scopes here https://developers.google.com/gmail/api/auth/scopes
# For instance, readonly scope is
# 'https://www.googleapis.com/auth/gmail.readonly'

credentials = get_gmail_credentials(
    token_file="token.json",
    scopes=["https://mail.google.com/"],
    client_secrets_file="credentials.json",
)
api_resource = build_resource_service(credentials=credentials)
toolkit = GmailToolkit(api_resource=api_resource)

# creamos la lista de herramientas de gmail
tools = toolkit.get_tools()

search = TavilySearchResults(max_results=2)
tools.append(search)
tools.append(redact_email)
tools.append(list_calendar_events)
tools.append(create_calendar_event)
tools.append(get_company_info)
tools.append(get_current_date_and_time)

system_prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            "Eres Mariana, el asistente virtual de OneCluster, una empresa de "
            "software que ofrece soluciones personalizadas. Asume el tono de "
            "J.A.R.V.I.S.: cordial, atento y con tacto en todo momento."
        ),
        ("system",
         "Preséntate como Mariana en el primer mensaje y pregunta el nombre "
         "del usuario si no lo tienes registrado."
         ),
        ("system",
         "Si el usuario ya ha interactuado antes, usa su nombre sin necesidad "
         "de volver a preguntar."
         ),
        ("system",
         "Si el primer mensaje del usuario es una solicitud, pregúntale su "
         "nombre antes de responder si aún no lo conoces."
         ),
        ("system",
         "OneCluster es una empresa de software especializada en desarrollo a "
         "medida. Solo responde a preguntas y solicitudes relacionadas con la "
         "empresa y sus servicios."
         ),
        ("system",
         "Si necesitas información adicional sobre la empresa, usa la función "
         "get_company_info."
         ),
        ("system",
         "Antes de enviar correos o crear eventos, muestra los detalles al "
         "usuario para que los confirme antes de ejecutar la tarea."
         ),
        ("system",
         "Si te preguntan algo no relacionado con los servicios de OneCluster,"
         " responde que solo puedes ayudar con temas relacionados con la "
         "empresa y sus soluciones."
         ),
        (
            "system",
            "Evita mencionar o hacer alusión a las herramientas que utilizas "
            "internamente. Esa información es confidencial."
        ),
        ("placeholder", "{messages}"),
    ]
)


class State(TypedDict):
    messages: Annotated[list, add_messages]
    is_last_step: bool  # Cambiar a booleano si es necesario


# Creamos el graph con el estado definido
graph = create_react_agent(
    model=llm,
    tools=tools,
    state_schema=State,
    state_modifier=system_prompt,
    checkpointer=MemorySaver()
)

config = {"configurable": {"thread_id": "thread-1", "recursion_limit": 50}}


while True:
    user_input = input("User: ")
    if user_input.lower() in ["quit", "exit", "q"]:
        print("Goodbye!")
        break

    events = graph.stream({
        "messages": [("user", user_input)],
        "is_last_step": False},
        config, stream_mode="updates")

    for event in events:
        if "agent" in event:
            print(f"\nAsistente: {event['agent']['messages'][-1].content}\n")