"""Auto-Re-Sync der Action-Bar-Belegung im Spiel-Loop.

Prueft im Smart-Modus periodisch, ob die verknuepften Traenke/Zauber noch
in ihren Slots liegen. Bei Abweichung (Action Bar wurde im Client
umgebaut) scannt der Bot automatisch neu und aktualisiert den
Live-Kontext — der "Hotkeys syncen"-Button ist damit nur noch fuer den
ersten Sync noetig.

ponytail: Schreibt nur den Live-Kontext, nicht die Profil-DB (kein
DB-Zugriff im Loop). Grenze: nach Bot-Neustart gilt die zuletzt manuell
gesyncte Belegung (Upgrade-Trigger: Re-Sync auch persistieren).
"""
from time import time

from src.gameplay.healing.syncHotkeys import _assignComboSlots, _assignSpellSlots
from src.gameplay.monitoring import logEvent
from src.repositories.actionBar.slotIcons import (
    SLOT_ITEM_ICONS, SLOT_SPELL_ICONS, detectSlotItems, detectSlotSpells,
    getSlotImage, matchSlotImage,
)

VERIFY_INTERVAL_SECONDS = 5


def _spellRuleName(key, rule):
    if key == 'utura':
        return 'utura'
    if key == 'uturaGran':
        return 'utura gran'
    spell = rule.get('spell')
    if isinstance(spell, dict):
        return spell.get('name')
    return spell


def _expectedBindings(context):
    """(icon, slot)-Paare aller verknuepften Traenke und Zauber."""
    bindings = []
    potions = context['healing']['potions']
    for key in ('firstHealthPotion', 'firstManaPotion'):
        potion = potions.get(key) or {}
        icon = SLOT_ITEM_ICONS.get(potion.get('item'))
        if icon is not None and potion.get('slot'):
            bindings.append((icon, potion['slot']))
    spells = context['healing'].get('spells', {})
    for key in ('criticalHealing', 'lightHealing', 'mediumHealing', 'utura', 'uturaGran'):
        rule = spells.get(key) or {}
        icon = SLOT_SPELL_ICONS.get(_spellRuleName(key, rule))
        if icon is not None and rule.get('slot'):
            bindings.append((icon, rule['slot']))
    for combo in context.get('ng_comboSpells', {}).get('items', []):
        for spell in combo.get('spells', []):
            icon = SLOT_SPELL_ICONS.get(spell.get('name'))
            if icon is not None and spell.get('slot'):
                bindings.append((icon, spell['slot']))
    return bindings


def _slotsAreStale(screenshot, bindings):
    for icon, slot in bindings:
        slotImage = getSlotImage(screenshot, slot)
        if slotImage is None:
            return None  # keine Action Bar sichtbar — nichts anfassen
        if matchSlotImage(slotImage, {0: icon}) is None:
            return True
    return False


def autoSyncActionBar(context):
    """Loop-Hook: erkennt Action-Bar-Umbauten und synct selbststaendig nach."""
    actionBar = context.get('ng_actionBar')
    if not actionBar or not actionBar.get('smartHotkeys'):
        return context
    now = time()
    if now - actionBar.get('lastVerifyAt', 0) < VERIFY_INTERVAL_SECONDS:
        return context
    actionBar['lastVerifyAt'] = now
    bindings = _expectedBindings(context)
    if not bindings:
        return context
    stale = _slotsAreStale(context['ng_screenshot'], bindings)
    if stale is not True:
        return context
    screenshot = context['ng_screenshot']
    items = detectSlotItems(screenshot)
    spellsDetected = detectSlotSpells(screenshot)
    if items is None:
        return context
    actionBar['slots'] = {str(itemId): slot for itemId, slot in items.items()}
    potions = context['healing']['potions']
    for key in ('firstHealthPotion', 'firstManaPotion'):
        potion = potions.get(key)
        if potion and potion.get('item'):
            potion['slot'] = items.get(potion['item'])
    if context['healing'].get('spells'):
        _assignSpellSlots(context['healing']['spells'], spellsDetected)
    _assignComboSlots(context.get('ng_comboSpells', {}).get('items', []), spellsDetected)
    logEvent('actionBarAutoSync', {
        'items': len(items), 'spells': len(spellsDetected or {})})
    return context
