"""
Anthropic Claude API handler (Messages API over raw HTTP -- Kodi has no pip/SDK).

Current models (claude-haiku-5-5, claude-sonnet-5-5, claude-opus-5-5)
think, reject sampling parameters (temperature/top_p/top_k), and return a
`thinking` block before the text -- so depth is set with output_config.effort,
max_tokens leaves room for thinking, and the answer is read from text blocks.
Refusals (stop_reason "refusal") are rerouted server-side via fallbacks (not on Haiku 5.5: its refusal is the answer).
"""

import time

import requests
import xbmc
import xbmcaddon

from wcs.ai.DialogAIDebugRequest import show_api_request_debug, show_api_response_debug, show_api_error_debug
from wcs.ai.model_catalog import CLAUDE_EFFORT_MODELS, CLAUDE_FALLBACK_MODELS, DEFAULT_MODEL, model_or_default

API_BASE_URL = "https://api.anthropic.com"
API_VERSION = "2023-06-01"
FALLBACK_BETA = "server-side-fallback-2026-07-01"


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


def _headers(api_key, model):
    headers = {
        "x-api-key": api_key,
        "anthropic-version": API_VERSION,
        "Content-Type": "application/json",
        "Accept": "application/json",
    }
    if model in CLAUDE_FALLBACK_MODELS:
        headers["anthropic-beta"] = FALLBACK_BETA
    return headers


def _extract_text(data):
    """Join text blocks; thinking/fallback blocks carry no answer text."""
    return "".join(block.get("text", "") for block in data.get("content", [])
                   if block.get("type") == "text").strip()


def send_prompt(prompt: str, model: str = None, **kwargs) -> tuple:
    """
    Odešle prompt na Anthropic Claude API.

    Args:
        prompt (str): Text promptu (použije se, když nejsou předány `messages`)
        model (str, optional): Specifický model (pokud None, použije se z nastavení)

    Returns:
        tuple: (response_text, usage_data) nebo s include_raw i (…, data, latency)
    """
    addon = xbmcaddon.Addon()
    api_key = addon.getSetting("anthropic_api_key")
    if not api_key:
        raise ValueError("Anthropic API klíč není nastaven.")

    context_titles = kwargs.get('context_titles')
    context_limit = kwargs.get('context_limit')
    system_prompt = kwargs.get('system_prompt')
    model = model or get_current_model()
    max_tokens = int(kwargs.get("max_output_tokens") or addon.getSetting("anthropic_max_tokens") or "16000")
    effort = addon.getSetting("anthropic_effort") or "low"

    messages_list = kwargs.get('messages')
    if messages_list:
        messages = [{"role": msg['role'], "content": msg['content']} for msg in messages_list]
    else:
        messages = [{"role": "user", "content": prompt}]

    payload = {"model": model, "max_tokens": max_tokens, "messages": messages}
    if system_prompt:
        payload["system"] = system_prompt
    if model in CLAUDE_EFFORT_MODELS:
        payload["output_config"] = {"effort": effort}
    if model in CLAUDE_FALLBACK_MODELS:
        payload["fallbacks"] = "default"

    url = f"{API_BASE_URL}/v1/messages"
    try:
        xbmc.log(f"[Anthropic API] Odesílám prompt na model {model}", xbmc.LOGINFO)

        # Debug dialog expects the system prompt as the first message
        debug_messages = ([{"role": "system", "content": system_prompt}] if system_prompt else []) + messages
        debug_payload = {"messages": debug_messages, "model": model, "max_tokens": max_tokens,
                         "effort": payload.get("output_config", {}).get("effort")}
        if not kwargs.get('private_content', False) and not show_api_request_debug("Anthropic", 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(api_key, model), json=payload,
                                 timeout=kwargs.get('request_timeout', 180))
        latency = time.time() - start_time
        if response.status_code >= 400:
            detail = response.text[:500]
            raise requests.exceptions.HTTPError(f"HTTP {response.status_code}: {detail}", response=response)
        data = response.json()

        if data.get("stop_reason") == "refusal":
            category = (data.get("stop_details") or {}).get("category")
            response_text = "Model odmítl odpovědět (kategorie: {}).".format(category or "neuvedena")
            xbmc.log(f"[Anthropic API] Refusal, category={category}", xbmc.LOGWARNING)
        else:
            response_text = _extract_text(data) or "Chyba: Neplatná odpověď z Anthropic API"
            if data.get("stop_reason") == "max_tokens":
                xbmc.log("[Anthropic API] Odpověď useknuta limitem max_tokens", xbmc.LOGWARNING)

        if not kwargs.get('private_content', False):
            show_api_response_debug("Anthropic Claude", model, data, response_text, latency=latency)

        usage = data.get('usage', {})
        usage_data = {
            'input_tokens': usage.get('input_tokens', 0),
            'output_tokens': usage.get('output_tokens', 0),
            'cached_input_tokens': usage.get('cache_read_input_tokens', 0),
            'cache_creation_input_tokens': usage.get('cache_creation_input_tokens', 0),
            'total_tokens': usage.get('input_tokens', 0) + usage.get('output_tokens', 0),
        }

        xbmc.log(f"[Anthropic API] Úspěšně získána odpověď: {len(response_text)} znaků (model {data.get('model', model)})", xbmc.LOGINFO)
        if kwargs.get('include_raw', False):
            return response_text, usage_data, data, latency
        return response_text, usage_data

    except requests.exceptions.RequestException as e:
        error_msg = f"Chyba při komunikaci s Anthropic API: {str(e)}"
        xbmc.log(f"[Anthropic API] {error_msg}", xbmc.LOGERROR)
        show_api_error_debug("Anthropic Claude", model, error_msg, {"exception": str(e)})
        raise Exception(error_msg)
    except Exception as e:
        error_msg = f"Neočekávaná chyba v Anthropic API: {str(e)}"
        xbmc.log(f"[Anthropic API] {error_msg}", xbmc.LOGERROR)
        show_api_error_debug("Anthropic Claude", model, error_msg, {"exception": str(e)})
        raise Exception(error_msg)


def validate_api_key():
    """
    Ověří platnost API klíče přes GET /v1/models (bez spotřeby tokenů).

    Returns:
        bool: True pokud je klíč platný, False jinak
    """
    addon = xbmcaddon.Addon()
    api_key = addon.getSetting("anthropic_api_key")
    if not api_key:
        return False
    try:
        response = requests.get(f"{API_BASE_URL}/v1/models",
                                headers={"x-api-key": api_key, "anthropic-version": API_VERSION},
                                timeout=10)
        if response.status_code == 200:
            return True
        xbmc.log(f"[wcs][anthropic_api] validate_api_key: HTTP {response.status_code}", xbmc.LOGWARNING)
        return False
    except requests.exceptions.RequestException as e:
        xbmc.log(f"[wcs][anthropic_api] validate_api_key: Síťová chyba - {e}", xbmc.LOGWARNING)
        return False
