"""Motor principal del chatbot conversacional."""

import logging
import sys
from pathlib import Path

from groq import Groq

from config import (
    GROQ_API_KEY,
    MAX_INPUT_LENGTH,
    MODEL_NAME,
    MSG_EMPTY,
    MSG_FALLBACK,
    MSG_TOO_LONG,
    SYSTEM_PROMPT,
    TEMPERATURE,
    USE_RAG,
)
from guardrails import check_input, check_output
from memory import ConversationMemory

# RAG
RAG_AVAILABLE = False
if(USE_RAG):
    sys.path.insert(0, str(Path(__file__).parent.parent))
    try:
        import rag
        RAG_AVAILABLE = True
    except ImportError:
        pass

logger = logging.getLogger(__name__)
memory = ConversationMemory()


def respond(user_message: str, session_id: str = "default") -> str:
    """Procesa un mensaje y devuelve una respuesta de texto."""
    try:
        if user_message is None:
            user_message = ""

        user_message = user_message.strip()
        if not user_message:
            return MSG_EMPTY
        if len(user_message) > MAX_INPUT_LENGTH:
            return MSG_TOO_LONG

        safe, message_or_rejection = check_input(user_message)
        if not safe:
            logger.warning(f"Mensaje bloqueado en sesión '{session_id}'")
            return message_or_rejection

        history = memory.get_history(session_id)

        # RAG (opcional)
        rag_context = ""
        if RAG_AVAILABLE:
            result = rag.query(user_message)
            if result.chunks:
                rag_context = "\n\n".join(
                    f"Fuente: {c.source}\n{c.text}"
                    for c in result.chunks
                )
                logger.info(
                    f"RAG: {len(result.chunks)} chunks recuperados para sesión {session_id}"
                )

        # Construir lista de mensajes para el LLM
        system_content = SYSTEM_PROMPT
        if rag_context:
            system_content = system_content.replace("{rag_context}", rag_context)

        messages = [{"role": "system", "content": system_content}]
        messages.extend(history)
        messages.append({"role": "user", "content": user_message})

        raw_response = _call_groq(messages)

        safe, final_response = check_output(raw_response)
        if not safe:
            logger.warning(f"Respuesta del LLM rechazada en sesión {session_id}")
            return final_response

        memory.add_turn(session_id, "user", user_message)
        memory.add_turn(session_id, "assistant", final_response)

        logger.info(
            f"Sesión {session_id} | entrada: {len(user_message)} chars | respuesta: {len(final_response)} chars"
        )
        return final_response

    except Exception as exc:
        logger.error(f"Error inesperado en sesión '{session_id}': {exc}", exc_info=True)
        return MSG_FALLBACK


def _call_groq(messages: list[dict]) -> str:
    """Llama a la API de Groq."""
    client = Groq(api_key=GROQ_API_KEY)
    completion = client.chat.completions.create(
        model=MODEL_NAME,
        messages=messages,
        temperature=TEMPERATURE,
    )
    return completion.choices[0].message.content


def reset_session(session_id: str) -> None:
    """Limpia el historial de una sesión."""
    memory.clear_session(session_id)
    logger.info(f"Sesión {session_id} reiniciada.")


if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO, format="%(levelname)s | %(message)s")
    print("Escribe 'salir' para terminar, '/reset' para nueva sesión.\n")

    session = "consola"
    while True:
        user_input = input("Mensaje: ").strip()
        if not user_input:
            continue
        if user_input.lower() == "salir":
            print("Bot: ¡Hasta luego!")
            break
        if user_input.lower() == "/reset":
            reset_session(session)
            print("Bot: Sesión reiniciada. ¿En qué te puedo ayudar?")
            continue

        response = respond(user_input, session_id=session)
        print(f"Bot: {response}")
