"""
Mistral AI API handler
Kompletní implementace pro Mistral AI API podle oficiální dokumentace
"""

import os
import requests
import xbmcaddon
import xbmc
import json
from wcs.ai.DialogAIDebugRequest import show_api_request_debug, show_api_response_debug, show_api_error_debug

# Načtení nastavení addonu
addon = xbmcaddon.Addon()
API_BASE_URL = "https://api.mistral.ai/v1"

def get_current_model():
    """Vrací aktuálně vybraný Mistral model z nastavení."""
    addon = xbmcaddon.Addon()
    selected_model = addon.getSetting("mistral_model")
    if not selected_model:
        selected_model = "mistral-large-latest"  # Výchozí model
    return selected_model

def send_prompt(prompt: str, model: str = None) -> tuple:
    """
    Odešle prompt na Mistral AI API.
    
    Args:
        prompt (str): Text promptu
        model (str, optional): Specifický model (pokud None, použije se z nastavení)
        
    Returns:
        tuple: (response_text, usage_data)
    """
    addon = xbmcaddon.Addon()
    API_KEY = addon.getSetting("mistral_api_key")
    
    if not API_KEY:
        raise ValueError("Mistral API klíč není nastaven.")
    
    # Pokud není model specifikován, použij model z nastavení
    if model is None:
        model = get_current_model()
    
    url = f"{API_BASE_URL}/chat/completions"
    
    headers = {
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
        "Accept": "application/json"
    }
    
    # Načtení parametrů z nastavení
    temperature = float(addon.getSetting("mistral_temperature") or "0.7")
    top_p = float(addon.getSetting("mistral_top_p") or "1.0")
    max_tokens = int(addon.getSetting("mistral_max_tokens") or "4096")
    random_seed = int(addon.getSetting("mistral_random_seed") or "0")

    payload = {
        "model": model,
        "messages": [
            {
                "role": "user",
                "content": prompt
            }
        ],
        "temperature": temperature,
        "max_tokens": max_tokens,
        "top_p": top_p
    }
    
    # Přidej random_seed pouze pokud není 0 (default)
    if random_seed != 0:
        payload["random_seed"] = random_seed

    try:
        xbmc.log(f"[Mistral API] Odesílám prompt na model {model}", xbmc.LOGINFO)
        
        # Debug: Zobrazí raw request před odesláním
        if not show_api_request_debug("Mistral AI", model, payload):
            raise Exception("Odeslání API requestu bylo zrušeno uživatelem.")
        
        response = requests.post(url, headers=headers, json=payload, timeout=120)
        response.raise_for_status()
        
        data = response.json()
        
        # Debug: Zobrazí raw response po obdržení
        
        # Extrakce odpovědi z Mistral API formátu
        if 'choices' in data and len(data['choices']) > 0:
            response_text = data['choices'][0]['message']['content']
        else:
            response_text = "Chyba: Neplatná odpověď z Mistral API"
        
        # Debug: Zobrazí response s extrahovaným textem
        show_api_response_debug("Mistral AI", model, data, response_text)
        
        # Extrakce usage informací (pokud jsou dostupné)
        usage_data = {}
        if 'usage' in data:
            usage_data = {
                'prompt_tokens': data['usage'].get('prompt_tokens', 0),
                'completion_tokens': data['usage'].get('completion_tokens', 0),
                'total_tokens': data['usage'].get('total_tokens', 0)
            }
        
        xbmc.log(f"[Mistral API] Úspěšně získána odpověď: {len(response_text)} znaků", xbmc.LOGINFO)
        
        return response_text, usage_data
        
    except requests.exceptions.RequestException as e:
        error_msg = f"Chyba při komunikaci s Mistral API: {str(e)}"
        xbmc.log(f"[Mistral API] {error_msg}", xbmc.LOGERROR)
        # Debug: Zobrazí chybu
        show_api_error_debug("Mistral AI", model, error_msg, {"exception": str(e)})
        raise Exception(error_msg)
    except Exception as e:
        error_msg = f"Neočekávaná chyba v Mistral API: {str(e)}"
        xbmc.log(f"[Mistral API] {error_msg}", xbmc.LOGERROR)
        # Debug: Zobrazí chybu
        show_api_error_debug("Mistral AI", model, error_msg, {"exception": str(e)})
        raise Exception(error_msg)

def get_available_models():
    """
    Získá seznam dostupných modelů z Mistral API.
    
    Returns:
        list: Seznam dostupných modelů
    """
    addon = xbmcaddon.Addon()
    API_KEY = addon.getSetting("mistral_api_key")
    
    if not API_KEY:
        return []
    
    url = f"{API_BASE_URL}/models"
    
    headers = {
        "Authorization": f"Bearer {API_KEY}",
        "Accept": "application/json"
    }
    
    try:
        response = requests.get(url, headers=headers, timeout=30)
        response.raise_for_status()
        
        data = response.json()
        
        # Extrakce názvů modelů
        models = []
        if 'data' in data:
            for model in data['data']:
                if 'id' in model:
                    models.append(model['id'])
        
        return models
        
    except Exception as e:
        xbmc.log(f"[Mistral API] Chyba při získávání seznamu modelů: {str(e)}", xbmc.LOGERROR)
        # Fallback seznam modelů podle dokumentace
        return [
            "magistral-medium-latest",
            "magistral-small-latest", 
            "mistral-medium-latest",
            "mistral-large-latest",
            "mistral-small-latest",
            "codestral-latest",
            "pixtral-large-latest",
            "ministral-8b-latest",
            "ministral-3b-latest",
            "open-mistral-nemo",
            "devstral-small-latest",
            "mistral-saba-latest"
        ]

def send_multimodal_prompt(text_prompt: str, image_data: str = None, model: str = None) -> tuple:
    """
    Odešle multimodální prompt (text + obrázek) na Mistral AI.
    
    Args:
        text_prompt (str): Textový prompt
        image_data (str, optional): Base64 kódovaný obrázek
        model (str, optional): Specifický model (doporučeno pixtral-large-latest)
        
    Returns:
        tuple: (response_text, usage_data)
    """
    addon = xbmcaddon.Addon()
    API_KEY = addon.getSetting("mistral_api_key")
    
    if not API_KEY:
        raise ValueError("Mistral API klíč není nastaven.")
    
    # Pro multimodální úlohy použij vhodný model
    if model is None:
        model = "pixtral-large-latest"
    
    url = f"{API_BASE_URL}/chat/completions"
    
    headers = {
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
        "Accept": "application/json"
    }
    
    # Sestavení zprávy s obrázkem
    content = [{"type": "text", "text": text_prompt}]
    
    if image_data:
        content.append({
            "type": "image_url",
            "image_url": {
                "url": f"data:image/jpeg;base64,{image_data}"
            }
        })
    
    # Načtení parametrů z nastavení
    temperature = float(addon.getSetting("mistral_temperature") or "0.7")
    top_p = float(addon.getSetting("mistral_top_p") or "1.0")
    max_tokens = int(addon.getSetting("mistral_max_tokens") or "4096")
    random_seed = int(addon.getSetting("mistral_random_seed") or "0")

    payload = {
        "model": model,
        "messages": [
            {
                "role": "user",
                "content": content
            }
        ],
        "temperature": temperature,
        "max_tokens": max_tokens,
        "top_p": top_p
    }
    
    # Přidej random_seed pouze pokud není 0 (default)
    if random_seed != 0:
        payload["random_seed"] = random_seed
    
    try:
        xbmc.log(f"[Mistral API] Odesílám multimodální prompt na model {model}", xbmc.LOGINFO)
        
        # Debug: Zobrazí raw multimodal request před odesláním
        show_api_request_debug("Mistral AI (Multimodal)", model, payload)
        
        response = requests.post(url, headers=headers, json=payload, timeout=120)
        response.raise_for_status()
        
        data = response.json()
        
        if 'choices' in data and len(data['choices']) > 0:
            response_text = data['choices'][0]['message']['content']
        else:
            response_text = "Chyba: Neplatná odpověď z Mistral API"
        
        # Debug: Zobrazí multimodal response
        show_api_response_debug("Mistral AI (Multimodal)", model, data, response_text)
        
        usage_data = {}
        if 'usage' in data:
            usage_data = data['usage']
        
        return response_text, usage_data
        
    except Exception as e:
        error_msg = f"Chyba při multimodálním zpracování: {str(e)}"
        xbmc.log(f"[Mistral API] {error_msg}", xbmc.LOGERROR)
        # Debug: Zobrazí multimodal chybu
        show_api_error_debug("Mistral AI (Multimodal)", model, error_msg, {"exception": str(e)})
        raise Exception(error_msg)

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("mistral_api_key")
    
    if not API_KEY:
        return False
    
    try:
        # Skutečné API volání pro ověření klíče
        url = f"{API_BASE_URL}/models"
        headers = {
            "Authorization": f"Bearer {API_KEY}",
            "Accept": "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][mistral_api] validate_api_key: Neplatný API klíč (401)", xbmc.LOGWARNING)
            return False
        else:
            xbmc.log(f"[wcs][mistral_api] validate_api_key: HTTP chyba {e.response.status_code}", xbmc.LOGWARNING)
            return False
    except requests.exceptions.RequestException as e:
        xbmc.log(f"[wcs][mistral_api] validate_api_key: Síťová chyba - {e}", xbmc.LOGWARNING)
        return False
    except Exception as e:
        xbmc.log(f"[wcs][mistral_api] validate_api_key: Neočekávaná chyba - {e}", xbmc.LOGWARNING)
        return False 