"""
Module: api_interface.py
--------------------------
Obsahuje funkce pro komunikaci s OpenAI API a správu konverzačního vlákna.
"""

import openai
import json
import time
import threading
import logging
from configparser import ConfigParser

logger = logging.getLogger("robovojtik.api_interface")
config = ConfigParser()
config.read("config.ini")

try:
    openai.api_key = config["OpenAI"]["api_key"]
except KeyError:
    raise ValueError("API key not found in config.ini. Zadejte 'api_key' do [OpenAI].")

ASSISTANT_ID = config["OpenAI"].get("assistant_id", None)
if not ASSISTANT_ID:
    raise ValueError("assistant_id not found in config.ini. Zadejte 'assistant_id' do [OpenAI].")

# Globální vlákno konverzace
thread_id = None

def vytvor_nove_vlakno():
    """
    Vytvoří nové vlákno konverzace s asistentem pomocí OpenAI API.
    """
    global thread_id
    try:
        thread = openai.beta.threads.create()
        thread_id = thread.id
        logger.debug(f"Vytvořeno nové vlákno: {thread_id}")
        return thread_id
    except Exception as e:
        logger.exception("Chyba při vytváření nového vlákna konverzace.")
        raise

def posli_dotaz_do_assistenta(prompt):
    """
    Odesílá dotaz v přirozeném jazyce do asistenta a vrací jeho odpověď.
    Ošetřuje stav "queued", "running", "pending" i "in_progress" tak, aby cyklus čekal na dokončení.
    Vrací poslední zprávu od asistenta.
    """
    global thread_id
    if thread_id is None:
        vytvor_nove_vlakno()
    logger.debug(f"Odesílám dotaz: {prompt}")

    openai.beta.threads.messages.create(
        thread_id=thread_id,
        role="user",
        content=prompt
    )
    run = openai.beta.threads.runs.create(
        thread_id=thread_id,
        assistant_id=ASSISTANT_ID
    )
    while True:
        run_status = openai.beta.threads.runs.retrieve(thread_id=thread_id, run_id=run.id)
        if run_status.status == "requires_action":
            handle_required_action(run_status, run.id, thread_id)
        elif run_status.status == "completed":
            break
        elif run_status.status in ["queued", "running", "pending", "in_progress"]:
            time.sleep(1)
        else:
            logger.warning(f"Neočekávaný stav run_status: {run_status.status}")
            time.sleep(1)
            break

    messages = openai.beta.threads.messages.list(thread_id=thread_id)
    answer = ""
    for msg in reversed(messages.data):
        if msg.role == "assistant" and msg.content and msg.content[0].text:
            answer = msg.content[0].text.value
            break
    logger.debug(f"Asistent odpověděl: {answer}")
    return answer

def handle_required_action(run_status, run_id, thread_id):
    """
    Vyřídí volání funkcí, které asistent vyžaduje (execute_shell_command, create_script, read_file).
    """
    from shell_functions import spust_prikaz, vytvor_skript, read_file_content

    try:
        tool_calls = run_status.required_action.submit_tool_outputs.tool_calls
        tool_outputs = []
        for tool_call in tool_calls:
            tool_name = tool_call.function.name
            logger.debug(f"Asistent volá funkci: {tool_name}")
            try:
                arguments = json.loads(tool_call.function.arguments)
            except Exception as e:
                logger.exception("Chyba při parsování argumentů pro funkci.")
                tool_outputs.append({
                    "tool_call_id": tool_call.id,
                    "output": "Chyba: Nepodařilo se přečíst argumenty."
                })
                continue

            if tool_name == "execute_shell_command":
                vysledek = spust_prikaz(arguments["command"])
            elif tool_name == "create_script":
                vysledek = vytvor_skript(arguments["file_name"], arguments["content"])
            elif tool_name == "read_file":
                vysledek = read_file_content(arguments["path"])
            else:
                vysledek = "Neznámá funkce."

            tool_outputs.append({
                "tool_call_id": tool_call.id,
                "output": vysledek
            })

        openai.beta.threads.runs.submit_tool_outputs(
            thread_id=thread_id,
            run_id=run_id,
            tool_outputs=tool_outputs
        )
    except Exception as e:
        logger.exception("Chyba při handle_required_action.")

def posli_prikaz_do_assistenta(command):
    """
    Odesílá schválený příkaz k vykonání do asistenta (např. cmd:).
    Ošetřuje stavy podobně jako posli_dotaz_do_assistenta.
    """
    global thread_id
    if thread_id is None:
        vytvor_nove_vlakno()
    logger.debug(f"Odesílám příkaz k vykonání: {command}")
    run = openai.beta.threads.runs.create(
        thread_id=thread_id,
        assistant_id=ASSISTANT_ID,
        instructions=f"Prosím, spusť tento příkaz: {command}"
    )
    while True:
        run_status = openai.beta.threads.runs.retrieve(thread_id=thread_id, run_id=run.id)
        if run_status.status == "requires_action":
            handle_required_action(run_status, run.id, thread_id)
        elif run_status.status == "completed":
            break
        elif run_status.status in ["queued", "running", "pending", "in_progress"]:
            time.sleep(1)
        else:
            logger.warning(f"Neočekávaný stav run_status: {run_status.status}")
            time.sleep(1)
            break
    messages = openai.beta.threads.messages.list(thread_id=thread_id)
    answer = ""
    for msg in reversed(messages.data):
        if msg.role == "assistant" and msg.content and msg.content[0].text:
            answer = msg.content[0].text.value
            break
    logger.debug(f"Výsledek spuštěného příkazu: {answer}")
    return answer

def volani_asistenta(prompt, spinner_func=None):
    """
    Spustí dotaz do asistenta v samostatném vlákně a během čekání volá spinner_func.
    Vrací odpověď asistenta nebo chybovou hlášku.
    """
    result_container = {}

    def worker():
        try:
            odpoved = posli_dotaz_do_assistenta(prompt)
            result_container['answer'] = odpoved
        except Exception as ex:
            result_container['answer'] = f"Chyba při volání asistenta: {str(ex)}"
            logger.exception("Chyba v worker funkci volani_asistenta.")

    thread = threading.Thread(target=worker)
    thread.start()
    idx = 0
    spinner = ["|", "/", "-", "\\"]
    while thread.is_alive():
        if spinner_func:
            spinner_func(spinner[idx % len(spinner)])
        time.sleep(0.2)
        idx += 1
    thread.join()
    return result_container.get('answer', "")

def reset_thread():
    """
    Resetuje konverzační vlákno tím, že nastaví globální thread_id na None.
    """
    global thread_id
    thread_id = None