"""Webshare API, konstanty vyhledávání a handlery historie / info / přehrání."""

from xml.etree import ElementTree as ET

import xbmcgui
import xbmcplugin

from resources.lib.utils.context_builder import style_context_menu
from resources.lib.auth.webshare_auth import WebshareClient

from resources.lib.core.router_state import (
    ADDON_ID,
    ADDON_NAME,
    _addon,
    _handle,
    _profile,
    get_url,
    log,
    popinfo,
)

API = 'https://webshare.cz/api/'
REALM = ':Webshare:'
CATEGORIES = ['', 'video', 'images', 'audio', 'archives', 'docs', 'adult']
SORTS = ['', 'recent', 'rating', 'largest', 'smallest']
SEARCH_HISTORY = 'search_history'
NONE_WHAT = '%#NONE#%'

_WS = None


def _ws_client():
    global _WS
    if _WS is None:
        _WS = WebshareClient(ADDON_ID)
    return _WS


def api(fnct, data):
    return _ws_client().api(fnct, data)


def revalidate():
    return _ws_client().revalidate()


def is_ok(xml):
    status_el = xml.find('status')
    return status_el is not None and (status_el.text or '') == 'OK'


def _vip_start_popup_if_needed(threshold_days=11):
    try:
        win = xbmcgui.Window(10000)
        if win.getProperty('mm_ws_vip_start_info_shown') == '1':
            return

        existing_token = _addon.getSetting('token') or ''
        if not existing_token:
            win.setProperty('mm_ws_vip_start_info_shown', '1')
            return

        resp = api('user_data', {'wst': existing_token})
        try:
            xml = ET.fromstring(resp.content)
        except Exception:
            win.setProperty('mm_ws_vip_start_info_shown', '1')
            return

        status_el = xml.find('status')
        if status_el is None or status_el.text != 'OK':
            win.setProperty('mm_ws_vip_start_info_shown', '1')
            return

        vip_days_txt = (xml.findtext('vip_days', '') or '').strip()
        vip_until = (xml.findtext('vip_until', '') or '').strip()
        try:
            vip_days = int(vip_days_txt) if vip_days_txt != '' else 0
        except Exception:
            vip_days = 0

        if vip_days < threshold_days:
            if vip_days <= 0:
                msg = "VIP není aktivní."
            else:
                msg = f"VIP: zbývá {vip_days} dní" + (
                    f" • do {vip_until}" if vip_until else ""
                )
            xbmcgui.Dialog().notification(
                ADDON_NAME, msg, xbmcgui.NOTIFICATION_INFO, 3500
            )

        win.setProperty('mm_ws_vip_start_info_shown', '1')
    except Exception as e:
        log.warning(f"VIP START POPUP skipped due to error: {e}")


def todict(xml, skip=None):
    if skip is None:
        skip = []
    result = {}
    for e in xml:
        if e.tag not in skip:
            value = e.text if len(list(e)) == 0 else todict(e, skip)
            if e.tag in result:
                if isinstance(result[e.tag], list):
                    result[e.tag].append(value)
                else:
                    result[e.tag] = [result[e.tag], value]
            else:
                result[e.tag] = value
    return result


def sizelize(txtsize, units=None):
    if units is None:
        units = ['B', 'KB', 'MB', 'GB']
    if txtsize:
        size = float(txtsize)
        if size < 1024:
            size = str(size) + units[0]
        else:
            size = size / 1024
            if size < 1024:
                size = str(int(round(size))) + units[1]
            else:
                size = size / 1024
                if size < 1024:
                    size = str(round(size, 2)) + units[2]
                else:
                    size = size / 1024
                    size = str(round(size, 2)) + units[3]
        return size
    return str(txtsize)


def labelize(file):
    if 'size' in file:
        size = sizelize(file['size'])
    elif 'sizelized' in file:
        size = file['sizelized']
    else:
        size = '?'
    label = file['name'] + ' (' + size + ')'
    return label


def tolistitem(file, addcommands=None):
    if addcommands is None:
        addcommands = []
    label = labelize(file)
    listitem = xbmcgui.ListItem(label=label)
    if 'img' in file:
        listitem.setArt({'thumb': file['img']})
    tag = listitem.getVideoInfoTag()
    tag.setTitle(label)
    listitem.setProperty('IsPlayable', 'true')

    if addcommands:
        addcommands = style_context_menu(addcommands)
        listitem.addContextMenuItems(addcommands, replaceItems=True)
    return listitem


def infonize(info, key, f=None, prefix=' - ', suffix='\n', showkey=True):
    text = ''
    if key in info and info[key]:
        if showkey:
            text += prefix + key + ': '
        else:
            text += prefix
        if f is None:
            text += info[key]
        else:
            text += f(info[key])
        text += suffix
    return text


def fpsize(txtfps):
    if txtfps:
        fps = float(txtfps)
        return str(round(fps, 2)) + 'fps'
    return str(txtfps)


def history(params):
    xbmcplugin.setPluginCategory(
        _handle, _addon.getAddonInfo('name') + " \\ Historie"
    )
    token = revalidate()
    updateListing = False
    if 'remove' in params:
        remove = params['remove']
        updateListing = True
        response = api('history', {'wst': token})
        xml = ET.fromstring(response.content)
        ids = []
        if is_ok(xml):
            for file in xml.iter('file'):
                if remove == file.find('ident').text:
                    ids.append(file.find('download_id').text)
        else:
            popinfo(
                "Chyba při komunikaci s Webshare API.",
                icon=xbmcgui.NOTIFICATION_WARNING,
            )
        if ids:
            response = api('clear_history', {'ids[]': ids, 'wst': token})
            xml = ET.fromstring(response.content)
            if is_ok(xml):
                popinfo("Soubor byl vymazán z historie.")
            else:
                popinfo(
                    "Chyba při komunikaci s Webshare API.",
                    icon=xbmcgui.NOTIFICATION_WARNING,
                )
    response = api('history', {'wst': token})
    xml = ET.fromstring(response.content)
    if is_ok(xml):
        for file in xml.iter('file'):
            item = todict(file)
            commands = []
            commands.append(
                (
                    "Smazat z historie",
                    'Container.Update('
                    + get_url(action='history', remove=item['ident'])
                    + ')',
                )
            )
            listitem = tolistitem(
                {
                    'ident': item.get('ident'),
                    'name': item.get('name'),
                    'sizelized': item.get('size'),
                },
                commands,
            )
            xbmcplugin.addDirectoryItem(
                _handle,
                get_url(
                    action='play',
                    ident=item.get('ident'),
                    name=item.get('name'),
                ),
                listitem,
                False,
            )
    else:
        popinfo(
            "Chyba při komunikaci s Webshare API.",
            icon=xbmcgui.NOTIFICATION_WARNING,
        )
    xbmcplugin.endOfDirectory(_handle, updateListing=updateListing)


def info(params):
    ident = params.get('ident', '')
    if ident.startswith('tt'):
        if 'title' in params:
            search_params = {
                'action': 'search',
                'q': params['title'],
            }
            from resources.lib.search.search_ui import search as search_fn

            search_fn(search_params)
            return
        else:
            popinfo(
                'Nelze vyhledat Webshare: Chybí název.',
                icon=xbmcgui.NOTIFICATION_WARNING,
            )
            xbmcplugin.endOfDirectory(_handle)
            return

    token = revalidate()
    response = api('file_info', {'ident': params['ident'], 'wst': token})
    xml = ET.fromstring(response.content)
    if is_ok(xml):
        info_data = todict(xml)
        text = ''
        text += infonize(info_data, 'name', showkey=False)
        text += infonize(info_data, 'upload_date')
        text += infonize(info_data, 'size', sizelize)
        text += infonize(info_data, 'length', showkey=False)
        text += infonize(info_data, 'rating')
        text += infonize(info_data, 'views')
        text += infonize(info_data, 'description')
        text += infonize(
            info_data,
            'bitrate',
            lambda x: sizelize(x, ['bps', 'Kbps', 'Mbps', 'Gbps']),
        )
        if 'video' in info_data and 'stream' in info_data['video']:
            streams = info_data['video']['stream']
            if isinstance(streams, dict):
                streams = [streams]
            for stream in streams:
                text += 'Video stream: '
                text += infonize(
                    stream, 'width', showkey=False, suffix=''
                )
                text += infonize(
                    stream,
                    'height',
                    showkey=False,
                    prefix='x',
                    suffix='',
                )
                text += infonize(
                    stream,
                    'format',
                    showkey=False,
                    prefix=', ',
                    suffix='',
                )
                text += infonize(
                    stream,
                    'fps',
                    fpsize,
                    showkey=False,
                    prefix=', ',
                    suffix='',
                )
                text += '\n'
        if 'audio' in info_data and 'stream' in info_data['audio']:
            streams = info_data['audio']['stream']
            if isinstance(streams, dict):
                streams = [streams]
            for stream in streams:
                text += 'Audio stream: '
                text += infonize(
                    stream, 'format', showkey=False, suffix=''
                )
                text += infonize(
                    stream,
                    'channels',
                    prefix=', ',
                    showkey=False,
                    suffix='',
                )
                text += infonize(
                    stream,
                    'bitrate',
                    lambda x: sizelize(
                        x, ['bps', 'Kbps', 'Mbps', 'Gbps']
                    ),
                    prefix=', ',
                    showkey=False,
                    suffix='',
                )
                text += '\n'
        text += infonize(
            info_data,
            'removed',
            lambda x: 'Yes' if x == '1' else 'No',
        )
        xbmcgui.Dialog().textviewer(_addon.getAddonInfo('name'), text)
    else:
        popinfo(
            'Vznikla chyba při komunikaci s Webshare API.',
            icon=xbmcgui.NOTIFICATION_WARNING,
        )
        xbmcplugin.endOfDirectory(_handle)


def play(params):
    from resources.lib.utils.play_handler import PlayHandler

    PlayHandler(_handle, _addon, _profile, _ws_client()).play(params)
