# wcs/streamcinema/SCClient.py
"""
Stream Cinema API client pro Milionář addon.
Poskytuje vyhledávání filmů/seriálů a získání ident pro KRA.sk resolve.

Flow:
1. KRA.sk login → session_id
2. SC /auth/token?krt=session_id → auth_token
3. SC API calls s X-AUTH-TOKEN header
"""

import requests
import xbmc
import xbmcgui
import uuid
from urllib.parse import urlencode, quote


BASE_URL = 'https://stream-cinema.online/kodi'
API_VERSION = '2.0'
UA = "Milionar/1.0 (Kodi)"

_session = requests.Session()
_session.headers.update({
    'User-Agent': UA,
    'Content-Type': 'application/json'
})

# Cache pro auth token
_auth_token_cache = None
_uuid = None


def _log(msg, level=xbmc.LOGINFO):
    """Logování s prefixem."""
    xbmc.log(f"[plugin.video.milionar] SCClient: {msg}", level=level)


def _get_uuid():
    """Získá nebo vytvoří UUID pro tuto instalaci."""
    global _uuid
    if _uuid is None:
        _uuid = str(uuid.uuid4())
    return _uuid


def _build_url(path, params=None):
    """
    Sestaví URL pro SC API volání.
    
    Args:
        path: API cesta (např. '/Search/search-movies')
        params: dict s parametry
    
    Returns:
        Kompletní URL string
    """
    url = BASE_URL + path
    
    # Vždy přidat výchozí parametry
    default_params = {
        'ver': API_VERSION,
        'uid': _get_uuid(),
        'skin': 'milionar',
        'lang': 'CS',
        'HDR': '1',
        'DV': '0'
    }
    
    # Merge s custom params (pokud jsou)
    all_params = {**default_params}
    if params:
        all_params.update(params)
    
    query_string = urlencode(all_params)
    url = f"{url}?{query_string}"
    
    return url


def _get_headers(auth_token=None):
    """Vrátí headers s auth tokenem."""
    headers = {
        'User-Agent': UA,
        'X-Uuid': _get_uuid()
    }
    if auth_token:
        headers['X-AUTH-TOKEN'] = auth_token
    return headers


def _api_get(path, params=None, auth_token=None, retries=3):
    """
    GET request na Stream Cinema API s retry logikou.
    
    Args:
        path: API cesta
        params: dict s query parametry
        auth_token: SC auth token
        retries: počet pokusů při 5xx chybách
    
    Returns:
        dict s odpovědí nebo None při chybě
    """
    import time
    url = _build_url(path, params)
    headers = _get_headers(auth_token)
    
    last_error = None
    for attempt in range(1, retries + 1):
        try:
            _log(f"API GET: {path}" + (f" (attempt {attempt}/{retries})" if attempt > 1 else ""))
            response = _session.get(url, headers=headers, timeout=15)
            response.raise_for_status()
            data = response.json()
            return data
        except Exception as e:
            last_error = e
            status = getattr(getattr(e, 'response', None), 'status_code', None)
            if status and 500 <= status < 600 and attempt < retries:
                _log(f"API {status} error on attempt {attempt}, retrying in 1s...", level=xbmc.LOGWARNING)
                time.sleep(1)
                continue
            _log(f"API error: {e}", level=xbmc.LOGERROR)
            return None
    
    _log(f"API failed after {retries} attempts: {last_error}", level=xbmc.LOGERROR)
    return None


def _api_post(path, params=None, data=None, auth_token=None):
    """
    POST request na Stream Cinema API.
    
    Args:
        path: API cesta
        params: dict s query parametry
        data: dict s body daty
        auth_token: SC auth token
    
    Returns:
        dict s odpovědí nebo None při chybě
    """
    url = _build_url(path, params)
    headers = _get_headers(auth_token)
    
    try:
        _log(f"API POST: {path}")
        response = _session.post(url, headers=headers, json=data, timeout=15)
        response.raise_for_status()
        return response.json()
    except Exception as e:
        _log(f"API error: {e}", level=xbmc.LOGERROR)
        return None


def get_auth_token(addon, kraska_session_id, force_refresh=False):
    """
    Získá Stream Cinema auth token pomocí KRA.sk session.
    
    Args:
        addon: xbmcaddon instance
        kraska_session_id: session_id z KRA.sk loginu
        force_refresh: vynutit nový token
    
    Returns:
        SC auth token nebo None
    """
    global _auth_token_cache
    
    # Zkusit cache
    if not force_refresh:
        cached = addon.getSetting('sc_auth_token')
        if cached:
            _auth_token_cache = cached
            return cached
    
    if not kraska_session_id:
        _log("Cannot get SC auth token: no KRA.sk session", level=xbmc.LOGWARNING)
        return None
    
    _log(f"Fetching SC auth token with KRA.sk session: {kraska_session_id[:8]}...")
    
    # POST na /auth/token s krt parametrem
    response = _api_post('/auth/token', params={'krt': kraska_session_id})
    
    if response and 'token' in response:
        token = response['token']
        addon.setSetting('sc_auth_token', token)
        _auth_token_cache = token
        _log(f"SC auth token obtained: {token[:8]}...")
        return token
    
    error = response.get('error', 'Unknown error') if response else 'Connection failed'
    _log(f"Failed to get SC auth token: {error}", level=xbmc.LOGERROR)
    return None


def is_authenticated(addon):
    """Zkontroluje, zda máme platný SC auth token."""
    token = addon.getSetting('sc_auth_token')
    return bool(token)


def search_movies(query, addon, limit=50):
    """
    Vyhledávání filmů přes Stream Cinema.
    
    Args:
        query: hledaný text
        addon: xbmcaddon instance
        limit: max počet výsledků
    
    Returns:
        list filmů nebo prázdný list
    """
    token = addon.getSetting('sc_auth_token')
    if not token:
        _log("Search failed: no auth token", level=xbmc.LOGWARNING)
        return []
    
    _log(f"Searching movies: {query}")
    
    params = {
        'search': query,
        'ms': '1'  # movie search flag
    }
    
    response = _api_get('/Search/search-movies', params=params, auth_token=token)
    
    if response and 'menu' in response:
        items = response['menu']
        _log(f"Found {len(items)} movies")
        return items
    
    return []


def search_series(query, addon, limit=50):
    """
    Vyhledávání seriálů přes Stream Cinema.
    
    Args:
        query: hledaný text
        addon: xbmcaddon instance
        limit: max počet výsledků
    
    Returns:
        list seriálů nebo prázdný list
    """
    token = addon.getSetting('sc_auth_token')
    if not token:
        _log("Search failed: no auth token", level=xbmc.LOGWARNING)
        return []
    
    _log(f"Searching series: {query}")
    
    params = {
        'search': query,
        'ms': '1',
        'typ': '2'  # 1=filmy, 2=seriály - KRITICKÉ pro správné vyhledávání!
    }
    
    response = _api_get('/Search/search-series', params=params, auth_token=token)
    
    # 🔍 DEBUG: Log the raw response
    _log(f"🔍 search_series raw response keys: {list(response.keys()) if response else 'None'}")
    
    if response and 'menu' in response:
        items = response['menu']
        _log(f"Found {len(items)} series")
        return items
    elif response and 'items' in response:
        items = response['items']
        return items
    elif response:
        for key, val in response.items():
            if isinstance(val, list) and len(val) > 0:
                return val
    
    return []


def get_streams(play_path, addon):
    """
    Získá seznam streamů pro daný film/epizodu.
    
    Args:
        play_path: cesta k přehrání (z menu itemu)
        addon: xbmcaddon instance
    
    Returns:
        list streamů nebo prázdný list
    """
    token = addon.getSetting('sc_auth_token')
    if not token:
        _log("Get streams failed: no auth token", level=xbmc.LOGWARNING)
        return []
    
    _log(f"Getting streams for: {play_path}")
    
    # Přidat prázdný params dict aby se přidaly výchozí parametry (ver, uid, skin, lang, HDR, DV)
    response = _api_get(play_path, params={}, auth_token=token)
    
    if response and 'strms' in response:
        streams = response['strms']
        _log(f"Found {len(streams)} streams")
        return streams
    
    
    return []


def get_ident(provider_path, addon, stream_prefs=None):
    """
    Získá ident pro KRA.sk resolve.
    
    Args:
        provider_path: cesta k provider endpointu (z stream.url)
        addon: xbmcaddon instance
        stream_prefs: volitelné preference streamu
    
    Returns:
        ident string nebo None
    """
    token = addon.getSetting('sc_auth_token')
    if not token:
        _log("Get ident failed: no auth token", level=xbmc.LOGWARNING)
        return None
    
    params = stream_prefs or {}
    
    _log(f"Getting ident from: {provider_path}")
    
    response = _api_get(provider_path, params=params, auth_token=token)
    
    if response and 'ident' in response:
        ident = response['ident']
        _log(f"Got ident: {ident}")
        return ident
    
    _log(f"No ident in response: {response}", level=xbmc.LOGWARNING)
    return None


def select_best_stream(streams, prefer_quality='1080p', prefer_lang='CZ'):
    """
    Vybere nejlepší stream podle preferencí.
    
    Args:
        streams: list streamů z get_streams()
        prefer_quality: preferovaná kvalita
        prefer_lang: preferovaný jazyk
    
    Returns:
        Nejlepší stream dict nebo None
    """
    if not streams:
        return None
    
    # Seřadit podle bitrate (nejvyšší první)
    sorted_streams = sorted(streams, key=lambda s: s.get('bitrate', 0), reverse=True)
    
    # Preferovat KRA.sk provider
    kraska_streams = [s for s in sorted_streams if s.get('provider', '').lower() == 'kraska']
    
    if kraska_streams:
        # Preferovat daný jazyk
        lang_match = [s for s in kraska_streams if s.get('lang', '').upper() == prefer_lang.upper()]
        if lang_match:
            return lang_match[0]
        return kraska_streams[0]
    
    # Fallback na první stream
    return sorted_streams[0] if sorted_streams else None


def resolve_stream(stream, addon):
    """
    Kompletní resolve streamu na finální URL.
    
    Args:
        stream: stream dict z get_streams()
        addon: xbmcaddon instance
    
    Returns:
        Finální stream URL nebo None
    """
    provider = stream.get('provider', '').lower()
    
    if provider == 'kraska':
        # KRA.sk provider - potřebujeme získat ident a pak resolvovat
        provider_path = stream.get('url')
        if not provider_path:
            _log("Stream has no provider path", level=xbmc.LOGWARNING)
            return None
        
        # Získat ident
        ident = get_ident(provider_path, addon)
        if not ident:
            _log("Failed to get ident", level=xbmc.LOGERROR)
            return None
        
        # Resolvovat přes KRA.sk
        from wcs.kraska import KraskaClient
        return KraskaClient.resolve(ident, addon)
    
    else:
        # Přímá URL
        url = stream.get('url')
        if url:
            _log(f"Direct stream URL: {url}")
            return url
    
    return None


def clear_auth(addon):
    """Vymaže uložený SC auth token."""
    addon.setSetting('sc_auth_token', '')
    global _auth_token_cache
    _auth_token_cache = None
    _log("SC auth token cleared")
