import requests
import xbmcaddon
import xbmc
import time
from wcs.ai.DialogAIDebugRequest import show_api_request_debug, show_api_response_debug
from wcs.ai.model_catalog import DEFAULT_MODEL, model_or_default

# Reasoning models (GPT-5+, o-series) take reasoning.effort and reject temperature/top_p
REASONING_PREFIXES = ("gpt-5", "gpt-6", "o1", "o3", "o4")


def get_current_model():
    """Vrací aktuálně vybraný OpenAI model z nastavení."""
    addon = xbmcaddon.Addon()
    return model_or_default('openai', addon.getSetting("openai_model") or DEFAULT_MODEL['openai'])

# Funkce pro odeslání promptu na OpenAI
def send_prompt(prompt: str, model: str = None, use_tools: bool = False, **kwargs) -> (str, dict):
    # Načtení nastavení addonu
    addon = xbmcaddon.Addon()
    API_KEY = addon.getSetting("openai_api_key")
    
    # Extra data pro debug
    context_titles = kwargs.get('context_titles')
    context_limit = kwargs.get('context_limit')
    system_prompt = kwargs.get('system_prompt')
    
    if not API_KEY:
        raise ValueError("OpenAI API klíč není nastaven.")
    
    # Pokud není model specifikován, použij model z nastavení
    if model is None:
        model = get_current_model()
    
    # Načtení parametrů z nastavení
    temperature = float(addon.getSetting("openai_temperature") or "1.0")
    top_p = float(addon.getSetting("openai_top_p") or "1.0")
    max_output_tokens = int(kwargs.get("max_output_tokens") or addon.getSetting("openai_max_output_tokens") or "16000")
    reasoning_effort = addon.getSetting("openai_reasoning_effort") or "medium"
    
    url = "https://api.openai.com/v1/responses"
    headers = {
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    }
    
    # === SESTAVENÍ STANDARDNÍCH MESSAGES ===
    # Standardní formát: [{role, content}] - stejný jako Groq/Mistral/Anthropic
    messages = []
    
    json_mode = kwargs.get('json_mode', False)
    
    messages_list = kwargs.get('messages', None)
    if messages_list:
        # Zkontrolovat jestli už messages obsahují system roli
        has_system = any(msg.get('role') == 'system' for msg in messages_list)
        
        # Přidat system prompt jako první, pokud není v messages a máme ho
        if system_prompt and not has_system:
            messages.append({"role": "system", "content": system_prompt})
            
        for i, msg in enumerate(messages_list):
            content = msg['content']
            # OpenAI Responses API vyžaduje slovo 'json' v input messages pro json_mode
            # Přidáme instrukci k první user zprávě
            if json_mode and i == 0 and msg['role'] == 'user':
                content = f"{content}\n\n[Odpověz ve formátu JSON.]"
            messages.append({"role": msg['role'], "content": content})
    else:
        # Jednoduchý prompt bez multi-turn
        if system_prompt:
            messages.append({"role": "system", "content": system_prompt})
        content = prompt
        if json_mode:
            content = f"{prompt}\n\n[Odpověz ve formátu JSON.]"
        messages.append({"role": "user", "content": content})
    
    # === TRANSFORMACE NA OPENAI RESPONSES API FORMÁT ===
    # OpenAI Responses API používá 'input' místo 'messages' a 'instructions' místo system role
    input_messages = [
        {"type": "message", "role": msg['role'], "content": msg['content']}
        for msg in messages if msg['role'] != 'system'
    ]
    
    is_reasoning_model = model.startswith(REASONING_PREFIXES)

    if is_reasoning_model:
        payload = {
            "model": model,
            "input": input_messages,
            "text": {"verbosity": "low"},
            "reasoning": {"effort": reasoning_effort},
            "max_output_tokens": max_output_tokens
        }
    else:
        payload = {
            "model": model,
            "input": input_messages,
            "temperature": temperature,
            "top_p": top_p,
            "max_output_tokens": max_output_tokens
        }
    
    # Přidat system prompt (instructions) pokud je definován
    if system_prompt:
        payload["instructions"] = system_prompt
    
    # JSON mode - vynutit JSON response formát
    json_mode = kwargs.get('json_mode', False)
    if json_mode:
        if "text" not in payload:
            payload["text"] = {}
        payload["text"]["format"] = {"type": "json_object"}
    
    # Přidat tools pouze pokud je to požadováno
    if use_tools:
        payload["tools"] = [{"type": "web_search"}]
    
    xbmc.log(f"[wcs][openai] URL: {url}", getattr(xbmc, 'LOGNOTICE', xbmc.LOGINFO))
    xbmc.log(f"[wcs][openai] Model: {model}", getattr(xbmc, 'LOGNOTICE', xbmc.LOGINFO))
    
    # === DEBUG PAYLOAD - messages už obsahují system pokud existuje ===
    debug_payload = {
        "messages": messages,
        "model": model,
        "temperature": temperature if not is_reasoning_model else None,
        "reasoning_effort": reasoning_effort if is_reasoning_model else None,
        "max_tokens": max_output_tokens
    }
    
    # Debug: Zobrazí standardní request před odesláním
    if not kwargs.get('private_content', False) and not show_api_request_debug("OpenAI", model, debug_payload, context_titles=context_titles, context_limit=context_limit):
        raise Exception("Odeslání API requestu bylo zrušeno uživatelem.")
    
    start_time = time.time()
    response = requests.post(url, headers=headers, json=payload, timeout=kwargs.get('request_timeout', 120))
    end_time = time.time()
    latency = end_time - start_time

    
    # Debug: Zobrazí raw response po obdržení
    try:
        response_data = response.json()
        if not kwargs.get('private_content', False):
            show_api_response_debug("OpenAI", model, response_data, latency=latency)
    except:
        if not kwargs.get('private_content', False):
            show_api_response_debug("OpenAI", model, {"raw_text": response.text}, latency=latency)
    
    response.raise_for_status()
    data = response.json()
    
    # Extract usage data
    usage = data.get("usage", {})
    
    # Build content from output events
    outputs = data.get("output", [])
    content = ""
    if isinstance(outputs, list):
        for evt in outputs:
            if isinstance(evt, dict) and evt.get("type") == "message":
                cont = evt.get("content")
                if isinstance(cont, list):
                    content = "".join(seg.get("text", "") for seg in cont if isinstance(seg, dict))
                else:
                    content = cont or evt.get("text", "")
                break
    
    # Fallback to 'choices' if no output events
    if not content:
        content = data.get("choices", [{}])[0].get("message", {}).get("content", "")
    
    if kwargs.get('include_raw', False):
        return content, usage, data, latency
        
    return content, usage

def validate_api_key():
    """
    Ověří platnost API klíče.
    
    Returns:
        bool: True pokud je klíč platný, False jinak
    """
    addon = xbmcaddon.Addon()
    API_KEY = addon.getSetting("openai_api_key")
    
    if not API_KEY:
        return False
    
    try:
        url = "https://api.openai.com/v1/models"
        headers = {
            "Authorization": f"Bearer {API_KEY}",
            "Content-Type": "application/json",
        }
        response = requests.get(url, headers=headers, timeout=10)
        response.raise_for_status()
        return True
    except requests.exceptions.HTTPError as e:
        if e.response.status_code == 401:
            xbmc.log("[wcs][openai_api] validate_api_key: Neplatný API klíč (401)", xbmc.LOGWARNING)
            return False
        else:
            xbmc.log(f"[wcs][openai_api] validate_api_key: HTTP chyba {e.response.status_code}", xbmc.LOGWARNING)
            return False
    except requests.exceptions.RequestException as e:
        xbmc.log(f"[wcs][openai_api] validate_api_key: Síťová chyba - {e}", xbmc.LOGWARNING)
        return False
    except Exception as e:
        xbmc.log(f"[wcs][openai_api] validate_api_key: Neočekávaná chyba - {e}", xbmc.LOGWARNING)
        return False
