from src.gameplay.core.tasks.castSpell import CastSpellTask
from src.gameplay.core.tasks.orchestrator import TasksOrchestrator
from src.gameplay.core.tasks.useHotkey import UseHotkeyTask
from src.gameplay.core.tasks.useSlotItem import UseSlotItemTask
from src.gameplay.core.tasks.useSpellHealHotkey import UseSpellHealHotkeyTask
from src.gameplay.reaction import ReactionGate
from src.repositories.actionBar.core import hasCooldownByName
from src.wiki.spells import spells
from ...typings import Context
from ..utils.potions import healthPotionTakesPriority


tasksOrchestrator = TasksOrchestrator()
spellGates = {}


def _gate(name):
    return spellGates.setdefault(name, ReactionGate())


def _spellName(value):
    """Zaubername aus Config (String oder {'name': ...}-Dict)."""
    if isinstance(value, dict):
        return value.get('name')
    return value


def _castTask(context, rule, spell, hotkeyTask):
    """Smart-Modus: Slot-Klick, sonst Chat-Zauber, sonst klassischer Hotkey."""
    if context.get('ng_actionBar', {}).get('smartHotkeys'):
        if rule.get('slot'):
            return UseSlotItemTask(rule['slot'])
        if spell:
            return CastSpellTask(spell)
    return hotkeyTask(rule['hotkey'])


def _hpMatches(rule, statusBar):
    """HP-Bedingung: absolute Schwelle (OCR) oder Prozent."""
    absolute = rule.get('hpLessThanOrEqual')
    if absolute is not None:
        return statusBar.get('hp') is not None and statusBar['hp'] <= absolute
    percentage = rule.get('hpPercentageLessThanOrEqual')
    return (percentage is not None
            and statusBar['hpPercentage'] <= percentage)


def _upkeepHpMatches(rule, statusBar):
    """HP-Bedingung fuer Upkeep-Zauber; ohne Schwelle (None/0) immer True."""
    absolute = rule.get('hpLessThanOrEqual')
    if absolute:
        return statusBar.get('hp') is not None and statusBar['hp'] <= absolute
    percentage = rule.get('hpPercentageLessThanOrEqual')
    if percentage:
        return statusBar['hpPercentage'] <= percentage
    return True


# TODO: add unit tests
def healingBySpells(context: Context):
    if healthPotionTakesPriority(context):
        return
    if context['ng_statusBar']['manaPercentage'] <= 30 and context['healing']['potions']['firstManaPotion']['enabled']:
        return
    # Notfall-Regel: unter 50 % HP reagiert jede Heilung in max. 1,2 s
    urgent = (context['ng_statusBar'].get('hpPercentage') or 100) < 50
    currentTask = tasksOrchestrator.getCurrentTask(context)
    if currentTask is not None:
        if currentTask.status == 'completed':
            tasksOrchestrator.reset()
        else:
            tasksOrchestrator.do(context)
            return
    critical = context['healing']['spells']['criticalHealing']
    if critical['enabled']:
        spell = _spellName(critical['spell'])
        if _gate('criticalHealing').ready(_hpMatches(critical, context['ng_statusBar']) and context['ng_statusBar']['mana'] >= spells[spell]['manaNeeded'] and not hasCooldownByName(context['ng_screenshot'], spell), urgent=urgent):
            tasksOrchestrator.setRootTask(
                context, _castTask(context, critical, spell, UseHotkeyTask))
            return
    light = context['healing']['spells']['lightHealing']
    if light['enabled']:
        spell = _spellName(light['spell'])
        if _gate('lightHealing').ready(_hpMatches(light, context['ng_statusBar']) and context['ng_statusBar']['mana'] >= spells[spell]['manaNeeded'] and not hasCooldownByName(context['ng_screenshot'], spell), urgent=urgent):
            tasksOrchestrator.setRootTask(
                context, _castTask(context, light, spell, UseSpellHealHotkeyTask))
            return
    medium = context['healing']['spells'].get('mediumHealing')
    if medium is not None and medium['enabled']:
        spell = _spellName(medium['spell'])
        if _gate('mediumHealing').ready(_hpMatches(medium, context['ng_statusBar']) and context['ng_statusBar']['mana'] >= spells[spell]['manaNeeded'] and not hasCooldownByName(context['ng_screenshot'], spell), urgent=urgent):
            tasksOrchestrator.setRootTask(
                context, _castTask(context, medium, spell, UseSpellHealHotkeyTask))
            return
    if context['healing']['spells']['utura']['enabled']:
        rule = context['healing']['spells']['utura']
        if _gate('utura').ready(_upkeepHpMatches(rule, context['ng_statusBar']) and context['ng_statusBar']['mana'] >= spells['utura']['manaNeeded'] and not hasCooldownByName(context['ng_screenshot'], 'utura'), urgent=urgent):
            tasksOrchestrator.setRootTask(
                context, _castTask(context, rule, 'utura', UseHotkeyTask))
            return
    if context['healing']['spells']['uturaGran']['enabled']:
        rule = context['healing']['spells']['uturaGran']
        if _gate('uturaGran').ready(_upkeepHpMatches(rule, context['ng_statusBar']) and context['ng_statusBar']['mana'] >= spells['utura gran']['manaNeeded'] and not hasCooldownByName(context['ng_screenshot'], 'utura gran'), urgent=urgent):
            tasksOrchestrator.setRootTask(
                context, _castTask(context, rule, 'utura gran', UseHotkeyTask))
