# -*- coding: utf-8 -*-
"""
MenuCacheServer: Úložiště mezipaměti menu mezi procesy pomocí vlastností okna Kodi.
Ukládá serializovaná data menu (JSON) v Window(10000) pro přístup napříč procesy.
"""

import json
import hashlib
from time import time
import xbmcgui
from resources.lib.utils.log_utils import get_logger

log = get_logger()

ADDON_ID = 'plugin.video.mmirousek_v3'
WINDOW_ID = 10000
CACHE_KEY_PREFIX = f'{ADDON_ID}.MenuCache'


def _hash_url(url: str) -> str:
    """Vytvoří bezpečný klíč mezipaměti z URL."""
    return hashlib.md5(url.encode()).hexdigest()[:12]


class MenuCacheServer(object):
    """
    Správce mezipaměti menu na straně serveru využívající vlastnosti okna Kodi.
    Umožňuje sdílení mezipaměti mezi procesy (hlavní doplněk ↔ service.py).
    """

    def __init__(self):
        """Inicializace odkazu na Window(10000)."""
        try:
            self.window = xbmcgui.Window(WINDOW_ID)
        except Exception as e:
            log.warning(f"[MenuCacheServer] Failed to init Window({WINDOW_ID}): {e}")
            self.window = None

    def _prop_key(self, url: str) -> str:
        """Vygeneruje klíč vlastnosti pro URL."""
        return f'{CACHE_KEY_PREFIX}.{_hash_url(url)}'

    def _serialize_items(self, items_list: list) -> list:
        """
        Serializuje položky menu do minimálního formátu bezpečného pro JSON.
        Každá položka: (url, popisek, isFolder, info_dict, art_dict, properties_dict, context_items, is_pinned)
        """
        serialized = []
        for item in items_list:
            try:
                if isinstance(item, tuple) and len(item) >= 2:
                    url, label = item[0], item[1]
                    isFolder = item[2] if len(item) > 2 else False
                    info = item[3] if len(item) > 3 else {}
                    art = item[4] if len(item) > 4 else {}
                    props = item[5] if len(item) > 5 else {}
                    context = item[6] if len(item) > 6 else []
                    is_pinned = item[7] if len(item) > 7 else False
                else:
                    # Přeskočit nesprávně zformátované položky
                    continue

                serialized.append({
                    'url': str(url) if url else '',
                    'label': str(label),
                    'isFolder': bool(isFolder),
                    'info': info if isinstance(info, dict) else {},
                    'art': art if isinstance(art, dict) else {},
                    'properties': props if isinstance(props, dict) else {},
                    'context': context if isinstance(context, list) else [],
                    'is_pinned': bool(is_pinned)
                })
            except Exception as e:
                log.debug(f"[MenuCacheServer] Serialize error for item: {e}")
                continue

        return serialized

    def cache_menu(self, url: str, items_list: list, max_age: int = 300) -> bool:
        """
        Uloží menu do mezipaměti uložením minimálních serializovaných dat do vlastnosti okna.
        
        Args:
            url: Identifikátor URL menu
            items_list: Seznam položek menu (n-tice nebo slovníky)
            max_age: Životnost mezipaměti (TTL) v sekundách (výchozí 5 min)
        
        Returns:
            True, pokud bylo úspěšně uloženo do mezipaměti
        """
        if not self.window:
            return False

        try:
            serialized = self._serialize_items(items_list)
            cache_data = {
                'version': 1,
                'timestamp': time(),
                'max_age': max_age,
                'url': url,
                'count': len(serialized),
                'items': serialized
            }

            prop_key = self._prop_key(url)
            json_str = json.dumps(cache_data, ensure_ascii=False)
            self.window.setProperty(prop_key, json_str)

            # Aktualizace registru pro hromadné vymazání
            registry_key = f'{CACHE_KEY_PREFIX}.__registry__'
            try:
                reg_str = self.window.getProperty(registry_key)
                registry = json.loads(reg_str) if reg_str else []
                if prop_key not in registry:
                    registry.append(prop_key)
                self.window.setProperty(registry_key, json.dumps(registry))
            except Exception:
                pass

            log.info(f"[MenuCacheServer] Cached {len(serialized)} items for {_hash_url(url)} (TTL: {max_age}s)")
            return True
        except Exception as e:
            log.warning(f"[MenuCacheServer] Cache write failed: {e}")
            return False

    def get_cached_menu(self, url: str):
        """
        Načte data menu z mezipaměti, pokud jsou platná a nevypršela.
        
        Args:
            url: Identifikátor URL menu
        
        Returns:
            Slovník s 'items', 'count', 'timestamp' nebo None při neúspěchu/vypršení
        """
        if not self.window:
            return None

        try:
            prop_key = self._prop_key(url)
            json_str = self.window.getProperty(prop_key)

            if not json_str:
                return None

            cache_data = json.loads(json_str)

            # Ověření stáří mezipaměti
            age = time() - cache_data.get('timestamp', 0)
            max_age = cache_data.get('max_age', 300)

            if age > max_age:
                log.info(f"[MenuCacheServer] Cache expired for {_hash_url(url)} (age: {age}s > {max_age}s)")
                self.invalidate_menu(url)
                return None

            log.info(f"[MenuCacheServer] Cache HIT for {_hash_url(url)} (age: {age:.1f}s, {cache_data.get('count')} items)")
            return cache_data

        except Exception as e:
            log.debug(f"[MenuCacheServer] Cache read error: {e}")
            return None

    def invalidate_menu(self, url: str = None) -> int:
        """
        Zneplatní položku(y) v mezipaměti.

        Args:
            url: Konkrétní URL k zneplatnění, nebo None pro vymazání všeho

        Returns:
            Počet vymazaných klíčů
        """
        if not self.window:
            return 0

        registry_key = f'{CACHE_KEY_PREFIX}.__registry__'
        try:
            if url:
                prop_key = self._prop_key(url)
                self.window.clearProperty(prop_key)
                log.info(f"[MenuCacheServer] Invalidated {_hash_url(url)}")
                # Odebrat z registru
                try:
                    reg_str = self.window.getProperty(registry_key)
                    registry = json.loads(reg_str) if reg_str else []
                    if prop_key in registry:
                        registry.remove(prop_key)
                        self.window.setProperty(registry_key, json.dumps(registry))
                except Exception:
                    pass
                return 1
            else:
                # Hromadné vymazání pomocí registru
                try:
                    reg_str = self.window.getProperty(registry_key)
                    prop_keys = json.loads(reg_str) if reg_str else []
                except Exception:
                    prop_keys = []
                count = 0
                for pk in prop_keys:
                    try:
                        self.window.clearProperty(pk)
                        count += 1
                    except Exception:
                        pass
                self.window.clearProperty(registry_key)
                log.info(f"[MenuCacheServer] Bulk clear: {count} menu cache entries removed")
                return count
        except Exception as e:
            log.warning(f"[MenuCacheServer] Invalidate failed: {e}")
            return 0

    def get_cache_stats(self) -> dict:
        """Vrátí statistiky mezipaměti (volitelné)."""
        return {
            'window_available': self.window is not None,
            'prefix': CACHE_KEY_PREFIX
        }


# Globální instance (singleton)
_cache_server = None


def get_menu_cache_server() -> MenuCacheServer:
    """Získá nebo vytvoří globální instanci MenuCacheServer."""
    global _cache_server
    if _cache_server is None:
        _cache_server = MenuCacheServer()
    return _cache_server
