import json
from typing import List
from fastapi import HTTPException
from openai import OpenAI
from openai.types.chat.chat_completion_message_function_tool_call import ChatCompletionMessageFunctionToolCall
from config.settings import OPENAI_API_KEY
from models.chat import Message
from models.user import User
from services.data_service import data_bg_loaded
from logging import getLogger
from services.openai_service.openai_tools import tools_list, tools

# Initialize OpenAI client
openai_client = OpenAI(api_key=OPENAI_API_KEY)

logger = getLogger(__name__)

data_for_prompt = [
    f'{{"pregunta": "{item.get("q", "")}", "respuesta": "{item.get("ans", "")}"}}'
    for item in data_bg_loaded
]
data_string = "\n".join(data_for_prompt)

async def generate_completion(messages_array: List[dict], user: User) -> str:

    messages = list(map(lambda x: f'<{x.get("username", "unknown")}> {x.get("message", "")}', messages_array))

    """Generate OpenAI chat completion"""
    if not OPENAI_API_KEY:
        logger.error("Error: OpenAI API key is not configured.")
        raise HTTPException(status_code=500, detail="OpenAI API key not configured on server.")

    logger.debug(f"Generating completion for user {user.email} with messages: {messages}")


    preprompt = f"""
¡Hola! Eres IAKlein, el asistente oficial del bar Klein 🍻.

Eres como ese amigo amigable que siempre está en la barra, listo para ayudar o tener una buena charla. Te comunicas en un estilo de chat corto (como mensajería o IRC), usando emojis y mucho carisma 😎.

Tu Rol:

Ser la guía experta del Menú: Conoces el menú . No solo "respondes", sino que inspiras. "Esa hamburguesa es increíble... 🤤"

El/La Amigo/a del Bar: Charlas, haces bromas y mantienes un buen ambiente. Si la conversación se desvía, ¡no hay problema! Tu pasión es el Klein, así que naturalmente vuelves al tema, pero sin presionar 🍺. Eres un anfitrión, no un vendedor.

El/La Recomendador/a Ideal: ¿Alguien no sabe qué pedir? ¡Ahí apareces tú! Preguntas qué les gusta y les ayudas a encontrar la opción perfecta.

El Buzón de Sugerencias (amigable): Si alguien tiene feedback, lo recibes muy bien y lo envías con la herramienta 'feedback'.

Tus Reglas Principales:

Informas, no tomas pedidos: "Te cuento todo sobre el menú, pero para pedir tienes que llamar al personal 😉".

Tu Identidad: Si te preguntan tu nombre... "¡Soy IAKlein! El corazón digital del Klein."

Prioridad @IAKlein: Atiendes al último usuario que te mencione (@IAKlein), usando el chat anterior como contexto si es necesario.

Evita Repetir: Si algo ya se respondió (por ti u otro), no intervienes. ¡A menos que insistan mucho!

Relax, es un Bar: No estás para resolver tareas, ni programar, ni hacer cálculos. Eres un compañero para pasar un buen rato, no un asistente genérico 🤖... ¡eres el espíritu del bar! 🕺

usa la siguiente informacion es toda tu memoria previa: 

{data_string}
"""


    processed_messages: List[dict] = [{"role": "system", "content": preprompt}]
    processed_messages.append(
        {"role": "user", "content": json.dumps(messages)}
    )

    try:
        completion = openai_client.chat.completions.create(
            model="gpt-4o-mini",
            messages=processed_messages,  # type: ignore (OpenAI lib expects list of specific dicts)
            temperature=0.7,
            tools=tools_list,
            tool_choice="auto",
        )
        calls = completion.choices[0].message.tool_calls
        if calls:
            logger.info(f"Tool calls: {calls}")
            for call in calls:
                if not isinstance(call, ChatCompletionMessageFunctionToolCall):
                    continue
                if call.function.name in tools:
                    tool_function = tools[call.function.name]
                    tool_args = json.loads(call.function.arguments)
                    logger.info(f"Calling tool: {call.function.name} with args: {tool_args}")
                    tool_response = tool_function(name=user.name, email=user.email, **tool_args)
                    logger.info(f"Tool response: {tool_response}")
                    completion.choices[0].message.content = tool_response
                else:
                    logger.warning(f"Tool {call.function.name} not found in tools dictionary.")

        response_content = completion.choices[0].message.content

        return response_content if response_content else "-1"
    except Exception as e:
        logger.error(f"Error calling OpenAI: {e}")
        raise HTTPException(status_code=500, detail="Error al procesar tu solicitud con OpenAI.")

def admin_completion(prompt: str, messages_array: List[dict]) -> str:
    """Generate OpenAI admin completion"""
    messages = list(map(lambda x: f'<{x.get("username", "unknown")}> {x.get("message", "")}', messages_array))
    
    if not OPENAI_API_KEY:
        logger.error("Error: OpenAI API key is not configured.")
        raise HTTPException(status_code=500, detail="OpenAI API key not configured on server.")

    try:
        completion = openai_client.chat.completions.create(
            model="gpt-4o-mini",
            messages=[
                {"role": "system", "content": f"""
IAKlein es el asistente oficial del bar Klein 🍻 y siempre se comunica en un estilo de chat corto, tipo mensajería o IRC, con emojis y mucho carisma. Su única función es entregar avisos oficiales del Biergarten Klein y no debe inventar ni agregar información extra. Los mensajes siempre deben integrarse a la conversación en curso, usando únicamente el chat como contexto para sonar naturales y sorpresivos. Cada aviso debe anunciarse con frases coloquiales como: “desde arriba me cuentan que…”, “me dicen que les pase el dato…”, “me informan que…”, o “me están pidiendo que diga que…” 😉. El tono tiene que ser siempre claro, positivo y cercano, asegurándose de transmitir toda la información sin omitir nada.

escribe el mensaje usando los ultimos mensajes de la siguiente lista por ejemplo "hablando de ...(conexion con el tema).. me dicen que...(mensaje oficial)..." o "me cuentan que...(mensaje oficial)..., hablando de ...(conexion con el tema)..."
mensajes: {messages}"""},
                {"role": "user", "content": prompt}
            ],
            temperature=0.7,
        )
        response_content = completion.choices[0].message.content
        return response_content if response_content else "-1"
    except Exception as e:
        logger.error(f"Error calling OpenAI for admin completion: {e}")
        raise HTTPException(status_code=500, detail="Error al procesar tu solicitud con OpenAI.")