from os.path import exists
from copy import deepcopy
from tinydb import Query, TinyDB
from tkinter import messagebox
from src.gameplay.core.load import loadContextFromConfig, loadNgCfgs
from src.gameplay.core.middlewares.window import setTibiaWindowMiddleware
from src.gameplay.death import DEFAULT_DEATH_CONFIG
from src.repositories.chat.core import resetOldList
from src.utils import ino
from src.utils.ino import ArduinoUnavailableError, requireArduino
# from src.utils.core import getScreenshot


class Context:
    filePath: str = 'file.json'

    def __init__(self, context):
        shouldInsertProfile = not exists(self.filePath)
        self.db = TinyDB(self.filePath)
        if shouldInsertProfile:
            self.insertProfile()
        self.enabledProfile = self.getEnabledProfile()
        # Alte Profile: neue Config-Felder aus den Defaults nachziehen.
        if _mergeMissing(self.enabledProfile['config'], self._defaultConfig()):
            self.db.update(self.enabledProfile)
        self.context = loadContextFromConfig(
            self.enabledProfile['config'], context)
        ino.setInputMethod(
            self.enabledProfile['config'].get(
                'input_method', ino.DEFAULT_INPUT_METHOD))

    def setInputMethod(self, method):
        normalised = ino.setInputMethod(method)
        self.enabledProfile['config']['input_method'] = normalised
        self.db.update(self.enabledProfile)
        return normalised

    def updateMainBackpack(self, backpack: str):
        self.context['ng_backpacks']['main'] = backpack
        self.enabledProfile['config']['ng_backpacks']['main'] = backpack
        self.db.update(self.enabledProfile)

    def insertProfile(self):
        self.db.insert({'enabled': True, 'config': self._defaultConfig()})

    @staticmethod
    def _defaultConfig():
        return {
                'ng_backpacks': {
                    'main': None,
                    'loot': None
                },
                'ng_cave': {
                    'enabled': False,
                    'runToCreatures': False,
                    'waypoints': {
                        'items': []
                    }
                },
                'ng_comboSpells': {
                    'enabled': False,
                    'items': []
                },
                'ng_supplies': {
                    'enabled': False,
                    'rules': []
                },
                'ng_lootRules': [],
                'ng_lootDropUnwanted': False,
                'ng_deathConfig': DEFAULT_DEATH_CONFIG.copy(),
                'ng_session': {
                    'enabled': False,
                    'huntMinutes': 240,
                    'offlineMinutes': 30,
                },
                'general_hotkeys': {
                    'shovel_hotkey': 'p',
                    'rope_hotkey': 'o'
                },
                'auto_hur': {
                    'enabled': False,
                    'hotkey': 't',
                    'spell': 'utani hur',
                    'pz': False
                },
                'alert': {
                    'enabled': False,
                    'cave': False,
                    'sayPlayer': False
                },
                'clear_stats': {
                    'poison': False,
                    'poison_hotkey': 'g'
                },
                'ignorable_creatures': [],
                'allies': [],
                'enemies': [],
                'healing': {
                    'highPriority': {
                        'healthFood': {
                            'enabled': False,
                            'hotkey': '3',
                            'hpPercentageLessThanOrEqual': 0,
                        },
                        'manaFood': {
                            'enabled': False,
                            'hotkey': '4',
                            'manaPercentageLessThanOrEqual': 0,
                        },
                        'swapRing': {
                            'enabled': False,
                            'tankRing': {
                                'hotkey': 'f11',
                                'hpPercentageLessThanOrEqual': 0,
                                'slot': 21
                            },
                            'mainRing': {
                                'hotkey': 'f12',
                                'hpPercentageGreaterThan': 0,
                                'slot': 22
                            },
                            'tankRingAlwaysEquipped': False
                        },
                        'swapAmulet': {
                            'enabled': False,
                            'tankAmulet': {
                                'hotkey': 'u',
                                'hpPercentageLessThanOrEqual': 0,
                                'slot': 23
                            },
                            'mainAmulet': {
                                'hotkey': 'i',
                                'hpPercentageGreaterThan': 0,
                                'slot': 24
                            },
                            'tankAmuletAlwaysEquipped': False
                        }
                    },
                    'potions': {
                        'firstHealthPotion': {
                            'enabled': False,
                            'hotkey': '1',
                            'slot': 1,
                            'hpPercentageLessThanOrEqual': 0,
                            'manaPercentageGreaterThanOrEqual': 0,
                        },
                        'firstManaPotion': {
                            'enabled': False,
                            'hotkey': '2',
                            'slot': 2,
                            'manaPercentageLessThanOrEqual': 0,
                        },
                    },
                    'spells': {
                        'criticalHealing': {
                            'enabled': False,
                            'hotkey': '5',
                            'hpPercentageLessThanOrEqual': 0,
                            'manaPercentageGreaterThanOrEqual': 0,
                            'spell': None
                        },
                        'lightHealing': {
                            'enabled': False,
                            'hotkey': '7',
                            'hpPercentageLessThanOrEqual': 0,
                            'manaPercentageGreaterThanOrEqual': 0,
                            'spell': None
                        },
                        'mediumHealing': {
                            'enabled': False,
                            'hotkey': '6',
                            'hpPercentageLessThanOrEqual': 0,
                            'manaPercentageGreaterThanOrEqual': 0,
                            'spell': None
                        },
                        'utura': {
                            'enabled': False,
                            'hotkey': '8',
                            'hpPercentageLessThanOrEqual': 0,
                            'manaPercentageGreaterThanOrEqual': 0,
                            'spell': None
                        },
                        'uturaGran': {
                            'enabled': False,
                            'hotkey': '9',
                            'hpPercentageLessThanOrEqual': 0,
                            'manaPercentageGreaterThanOrEqual': 0,
                            'spell': None
                        },
                    },
                    'eatFood': {
                        'enabled': False,
                        'hotkey': 'f',
                        'eatWhenFoodIslessOrEqual': 0,
                    }
                },
                'input_method': 'mac_bt',
            }

    def loadScript(self, script):
        self.context['ng_cave']['waypoints']['items'] = script.copy()
        self.enabledProfile['config']['ng_cave']['waypoints']['items'] = script.copy()
        self.db.update(self.enabledProfile)

    def importBBot(self, config):
        self.context['ng_pause'] = True
        self.context['ng_tasksOrchestrator'].reset()
        self.enabledProfile['config'] = config
        self.db.update(self.enabledProfile)
        self.context = loadContextFromConfig(config, self.context)

    def loadCfg(self, cfg):
        self.context = loadNgCfgs(cfg, self.context)
        self.enabledProfile['config']['ng_backpacks'] = self.context['ng_backpacks']
        self.enabledProfile['config']['general_hotkeys'] = self.context['general_hotkeys']
        self.enabledProfile['config']['auto_hur'] = self.context['auto_hur']
        self.enabledProfile['config']['alert'] = self.context['alert']
        self.enabledProfile['config']['clear_stats'] = self.context['clear_stats']
        self.enabledProfile['config']['ng_comboSpells']['enabled'] = self.context['ng_comboSpells']['enabled']
        for comboSpellsItem in self.context['ng_comboSpells']['items']:
            comboSpellsItem['currentSpellIndex'] = 0
            self.enabledProfile['config']['ng_comboSpells']['items'].append(comboSpellsItem)
        self.enabledProfile['config']['healing'] = self.context['healing']
        self.db.update(self.enabledProfile)

    def syncActionBarHotkeys(self):
        """Scannt die Action Bar und verknuepft Traenke/Zauber automatisch."""
        from src.gameplay.healing.syncHotkeys import syncActionBar
        screenshot = self.context.get('ng_screenshot')
        if screenshot is None:
            return False, 'Kein Screenshot — läuft der Bot?'
        ok, message = syncActionBar(screenshot, self.enabledProfile['config'])
        if ok:
            self.db.update(self.enabledProfile)
            self.context = loadNgCfgs(
                self.enabledProfile['config'], self.context)
        return ok, message

    def getSupplies(self):
        return self.context.get(
            'ng_supplies', {'enabled': False, 'rules': []})

    def getUiTheme(self):
        """Gewaehlte Akzentfarbe des Designs (Default: rosa)."""
        return self.enabledProfile['config'].get('ui_theme', 'rosa')

    def setUiTheme(self, name):
        self.enabledProfile['config']['ui_theme'] = name
        self.db.update(self.enabledProfile)

    def getUiMode(self):
        """Hell/Dunkel-Modus des Designs (Default: dunkel)."""
        return self.enabledProfile['config'].get('ui_mode', 'dunkel')

    def setUiMode(self, name):
        self.enabledProfile['config']['ui_mode'] = name
        self.db.update(self.enabledProfile)

    def getUiGlass(self):
        """Glas-Staerke 0-100 (Default: 100)."""
        return int(self.enabledProfile['config'].get('ui_glass', 100))

    def setUiGlass(self, value):
        self.enabledProfile['config']['ui_glass'] = int(value)
        self.db.update(self.enabledProfile)

    def getDeathConfig(self):
        """Todes-Config, fehlende Werte mit Defaults aufgefuellt."""
        config = DEFAULT_DEATH_CONFIG.copy()
        stored = self.enabledProfile['config'].get('ng_deathConfig') or {}
        for key in config:
            if stored.get(key) is not None:
                config[key] = stored[key]
        return config

    def setDeathConfig(self, config):
        stored = DEFAULT_DEATH_CONFIG.copy()
        for key in stored:
            if config.get(key) is not None:
                stored[key] = config[key]
        self.context['ng_deathConfig'] = stored.copy()
        self.enabledProfile['config']['ng_deathConfig'] = stored
        self.db.update(self.enabledProfile)

    def setSupplies(self, supplies):
        self.context['ng_supplies'] = supplies
        self.enabledProfile['config']['ng_supplies'] = supplies
        self.db.update(self.enabledProfile)

    def getSessionRhythm(self):
        return self.context.get('ng_session', {
            'enabled': False, 'huntMinutes': 240, 'offlineMinutes': 30,
        })

    def setSessionRhythm(self, enabled, huntMinutes, offlineMinutes):
        for target in (self.context, self.enabledProfile['config']):
            session = target.setdefault('ng_session', {})
            session['enabled'] = enabled
            session['huntMinutes'] = huntMinutes
            session['offlineMinutes'] = offlineMinutes
        self.db.update(self.enabledProfile)

    def scanOpenBackpacks(self):
        """Erkennt aktuell geoeffnete Backpacks auf dem Screenshot."""
        from src.repositories.inventory.core import detectOpenBackpacks
        screenshot = self.context.get('ng_screenshot')
        if screenshot is None:
            return {}
        found = detectOpenBackpacks(screenshot)
        self.context['ng_detectedBackpacks'] = found
        return found

    def runFullSetup(self):
        """Ein-Knopf-Setup: Backpacks erkennen + zuweisen, Gold-Regeln,
        Hotkeys syncen. Rueckgabe (ok, meldung)."""
        from src.gameplay.lootRouter import _findInContainer
        from src.repositories.actionBar.slotIcons import getItemIcon
        found = self.scanOpenBackpacks()
        names = sorted(found)
        if not names:
            return False, 'Keine Backpacks offen — bitte öffnen und erneut versuchen.'
        screenshot = self.context.get('ng_screenshot')
        potionIcon = getItemIcon(266)
        mainName = None
        if screenshot is not None and potionIcon is not None:
            for name in names:
                if _findInContainer(screenshot, found[name], potionIcon):
                    mainName = name
                    break
        if mainName is None:
            mainName = names[0]
        others = [name for name in names if name != mainName]
        lootName = others[0] if others else None
        self.updateMainBackpack(mainName)
        steps = [f'Main: {mainName}']
        if lootName:
            self.updateLootBackpack(lootName)
            rules = [rule for rule in self.getLootRules()
                     if rule.get('itemId') not in (3031, 3035)]
            rules.append({'itemId': 3031, 'to': lootName})
            rules.append({'itemId': 3035, 'to': lootName})
            self.setLootRules(rules)
            steps.append(f'Loot: {lootName} (+ Gold/Platin-Regeln)')
        else:
            steps.append('nur ein Backpack — kein Loot-Ziel')
        ok, message = self.syncActionBarHotkeys()
        steps.append('Hotkeys synchronisiert' if ok else f'Hotkeys: {message}')
        return True, ' · '.join(steps)

    def getLootRules(self):
        return self.context.get('ng_lootRules', [])

    def setLootRules(self, rules):
        self.context['ng_lootRules'] = rules
        self.enabledProfile['config']['ng_lootRules'] = rules
        self.db.update(self.enabledProfile)

    def getLootDropUnwanted(self):
        return bool(self.context.get('ng_lootDropUnwanted', False))

    def setLootDropUnwanted(self, enabled):
        self.context['ng_lootDropUnwanted'] = bool(enabled)
        self.enabledProfile['config']['ng_lootDropUnwanted'] = bool(enabled)
        self.db.update(self.enabledProfile)

    def isRecording(self):
        return self.context.get('ng_recording') is not None

    def toggleRecording(self):
        """Aufnahme an/aus; beim Stoppen wird die Route gespeichert."""
        from src.gameplay.recorder import finishRecording
        if self.context.get('ng_recording') is not None:
            waypoints = finishRecording(self.context['ng_recording'])
            self.context['ng_recording'] = None
            if waypoints:
                self.loadScript(waypoints)
            return False, len(waypoints)
        self.context['ng_recording'] = {'points': []}
        return True, 0

    def getEnabledProfile(self):
        return self.db.search(Query().enabled == True)[0]

    def updateLootBackpack(self, backpack: str):
        self.context['ng_backpacks']['loot'] = backpack
        self.enabledProfile['config']['ng_backpacks']['loot'] = backpack
        self.db.update(self.enabledProfile)

    def addWaypoint(self, waypoint):
        self.context['ng_cave']['waypoints']['items'].append(waypoint)
        self.enabledProfile['config']['ng_cave']['waypoints']['items'].append(
            waypoint)
        self.db.update(self.enabledProfile)

    def addCombo(self, combo):
        self.context['ng_comboSpells']['items'].append(combo)
        self.enabledProfile['config']['ng_comboSpells']['items'].append(
            combo)
        self.db.update(self.enabledProfile)

    def addIgnorableCreature(self, creature):
        self.context['ignorable_creatures'].append(creature)
        self.enabledProfile['config']['ignorable_creatures'].append(creature)
        self.db.update(self.enabledProfile)

    def addAlly(self, name):
        self.context.setdefault('allies', []).append(name)
        self.enabledProfile['config'].setdefault('allies', []).append(name)
        self.db.update(self.enabledProfile)

    def removeAlly(self, name):
        self.context.setdefault('allies', []).remove(name)
        self.enabledProfile['config'].setdefault('allies', []).remove(name)
        self.db.update(self.enabledProfile)

    def addEnemy(self, name):
        self.context.setdefault('enemies', []).append(name)
        self.enabledProfile['config'].setdefault('enemies', []).append(name)
        self.db.update(self.enabledProfile)

    def removeEnemy(self, name):
        self.context.setdefault('enemies', []).remove(name)
        self.enabledProfile['config'].setdefault('enemies', []).remove(name)
        self.db.update(self.enabledProfile)

    def addSpecialSqm(self, coordinate):
        sqm = [int(coordinate[0]), int(coordinate[1]), int(coordinate[2])]
        self.context['ng_cave'].setdefault('specialSqms', []).append(sqm)
        self.enabledProfile['config']['ng_cave'].setdefault(
            'specialSqms', []).append(sqm)
        self.db.update(self.enabledProfile)

    def removeSpecialSqm(self, index):
        self.context['ng_cave'].setdefault('specialSqms', []).pop(index)
        self.enabledProfile['config']['ng_cave'].setdefault(
            'specialSqms', []).pop(index)
        self.db.update(self.enabledProfile)

    def addSpellByIndex(self, index, spell):
        self.context['ng_comboSpells']['items'][index]['spells'].append(spell)
        # self.enabledProfile['config']['ng_comboSpells']['items'][index]['spells'].append(
        #     spell)
        self.db.update(self.enabledProfile)

    def getAllWaypointLabels(self):
        waypointsLabels = [waypointItem['label'] for waypointItem in self.context['ng_cave']
                        ['waypoints']['items'] if waypointItem['label'] != '']
        return waypointsLabels

    def hasWaypointWithLabel(self, label: str, ignoreLabel=None) -> bool:
        for waypoint in self.context['ng_cave']['waypoints']['points']:
            if waypoint['label'] == label and ignoreLabel is not None:
                return True
        return False

    def updateWaypointByIndex(self, waypointIndex, label=None, options={}):
        if label is not None:
            self.context['ng_cave']['waypoints']['items'][waypointIndex]['label'] = label
            self.enabledProfile['config']['ng_cave']['waypoints']['items'][waypointIndex]['label'] = label
        self.context['ng_cave']['waypoints']['items'][waypointIndex]['options'] = options
        self.enabledProfile['config']['ng_cave']['waypoints']['items'][waypointIndex]['options'] = options
        self.db.update(self.enabledProfile)

    def updateIgnorableCreatureByIndex(self, creatureIndex, name=None):
        if name is not None:
            self.context['ignorable_creatures'][creatureIndex] = name
            self.enabledProfile['config']['ignorable_creatures'][creatureIndex] = name
            self.db.update(self.enabledProfile)

    def removeWaypointByIndex(self, index):
        self.context['ng_cave']['waypoints']['items'].pop(index)
        self.enabledProfile['config']['ng_cave']['waypoints']['items'].pop(
            index)
        self.db.update(self.enabledProfile)

    def removeComboByIndex(self, index):
        self.context['ng_comboSpells']['items'].pop(index)
        self.enabledProfile['config']['ng_comboSpells']['items'].pop(
            index)
        self.db.update(self.enabledProfile)

    def removeIgnorableCreatureByIndex(self, index):
        self.context['ignorable_creatures'].pop(index)
        self.enabledProfile['config']['ignorable_creatures'].pop(index)
        self.db.update(self.enabledProfile)

    def play(self):
        try:
            requireArduino()
        except ArduinoUnavailableError as error:
            messagebox.showerror('PilotNG', str(error))
            self.context['ng_pause'] = True
            return False
        setTibiaWindowMiddleware(self.context)
        if self.context['window'] is None:
            messagebox.showerror(
                'Erro', 'Tibia window is not set!')
            return False
        # screenshot = getScreenshot()
        # chatTabs = getTabs(screenshot)
        # if 'loot' not in chatTabs:
        #     messagebox.showerror(
        #         'Erro', 'Loot tab must be open!')
        #     return
        self.context['ng_pause'] = False
        return True

    def pause(self):
        self.context['ng_pause'] = True
        self.context['ng_tasksOrchestrator'].setRootTask(self.context, None)
        self.context['ng_cave']['waypoints']['currentIndex'] = None
        self.context['loot']['corpsesToLoot'] = []
        resetOldList()

    def toggleHealingPotionsByKey(self, healthPotionType, enabled):
        self.context['healing']['potions'][healthPotionType]['enabled'] = enabled
        self.enabledProfile['config']['healing']['potions'][healthPotionType]['enabled'] = enabled
        self.db.update(self.enabledProfile)

    def toggleFoodByKey(self, enabled):
        self.context['healing']['eatFood']['enabled'] = enabled
        self.enabledProfile['config']['healing']['eatFood']['enabled'] = enabled
        self.db.update(self.enabledProfile)

    def toggleHealingHighPriorityByKey(self, key, enabled):
        self.context['healing']['highPriority'][key]['enabled'] = enabled
        self.enabledProfile['config']['healing']['highPriority'][key]['enabled'] = enabled
        self.db.update(self.enabledProfile)

    def setShovelHotkey(self, hotkey):
        self.context['general_hotkeys']['shovel_hotkey'] = hotkey
        self.enabledProfile['config']['general_hotkeys']['shovel_hotkey'] = hotkey
        self.db.update(self.enabledProfile)

    def setRopeHotkey(self, hotkey):
        self.context['general_hotkeys']['rope_hotkey'] = hotkey
        self.enabledProfile['config']['general_hotkeys']['rope_hotkey'] = hotkey
        self.db.update(self.enabledProfile)

    def setHotkeyHealingHighPriorityByKey(self, key, hotkey):
        self.context['healing']['highPriority'][key]['hotkey'] = hotkey
        self.enabledProfile['config']['healing']['highPriority'][key]['hotkey'] = hotkey
        self.db.update(self.enabledProfile)

    def setHealthFoodHpPercentageLessThanOrEqual(self, hpPercentageLessThanOrEqual):
        self.context['healing']['highPriority']['healthFood']['hpPercentageLessThanOrEqual'] = hpPercentageLessThanOrEqual
        self.enabledProfile['config']['healing']['highPriority']['healthFood'][
            'hpPercentageLessThanOrEqual'] = hpPercentageLessThanOrEqual
        self.db.update(self.enabledProfile)

    def setManaFoodHpPercentageLessThanOrEqual(self, manaPercentageLessThanOrEqual):
        self.context['healing']['highPriority']['manaFood']['manaPercentageLessThanOrEqual'] = manaPercentageLessThanOrEqual
        self.enabledProfile['config']['healing']['highPriority']['manaFood'][
            'manaPercentageLessThanOrEqual'] = manaPercentageLessThanOrEqual
        self.db.update(self.enabledProfile)

    def toggleSpellByKey(self, healthPotionType, enabled):
        self.context['healing']['spells'][healthPotionType]['enabled'] = enabled
        self.enabledProfile['config']['healing']['spells'][healthPotionType]['enabled'] = enabled
        self.db.update(self.enabledProfile)

    def setFoodHotkey(self, hotkey):
        self.context['healing']['eatFood']['hotkey'] = hotkey
        self.enabledProfile['config']['healing']['eatFood']['hotkey'] = hotkey
        self.db.update(self.enabledProfile)

    def setHealthPotionHotkeyByKey(self, healthPotionType, hotkey):
        self.context['healing']['potions'][healthPotionType]['hotkey'] = hotkey
        self.enabledProfile['config']['healing']['potions'][healthPotionType]['hotkey'] = hotkey
        self.db.update(self.enabledProfile)

    def setHealthPotionSlotByKey(self, healthPotionType, slot):
        self.context['healing']['potions'][healthPotionType]['slot'] = slot
        self.enabledProfile['config']['healing']['potions'][healthPotionType]['slot'] = slot
        self.db.update(self.enabledProfile)

    def setHealthPotionItemByKey(self, healthPotionType, item):
        self.context['healing']['potions'][healthPotionType]['item'] = item
        self.enabledProfile['config']['healing']['potions'][healthPotionType]['item'] = item
        self.db.update(self.enabledProfile)

    def setSpellHotkeyByKey(self, healthPotionType, hotkey):
        self.context['healing']['spells'][healthPotionType]['hotkey'] = hotkey
        self.enabledProfile['config']['healing']['spells'][healthPotionType]['hotkey'] = hotkey
        self.db.update(self.enabledProfile)

    def setHealthPotionHpPercentageLessThanOrEqual(self, healthPotionType, hpPercentage):
        self.context['healing']['potions'][healthPotionType]['hpPercentageLessThanOrEqual'] = hpPercentage
        self.enabledProfile['config']['healing']['potions'][healthPotionType]['hpPercentageLessThanOrEqual'] = hpPercentage
        self.db.update(self.enabledProfile)

    def setSwapRingHpPercentageLessThanOrEqual(self, hpPercentageLessThanOrEqual):
        self.context['healing']['highPriority']['swapRing']['tankRing']['hpPercentageLessThanOrEqual'] = hpPercentageLessThanOrEqual
        self.enabledProfile['config']['healing']['highPriority']['swapRing']['tankRing'][
            'hpPercentageLessThanOrEqual'] = hpPercentageLessThanOrEqual
        self.db.update(self.enabledProfile)

    def setSwapTankRingHotkey(self, hotkey):
        self.context['healing']['highPriority']['swapRing']['tankRing']['hotkey'] = hotkey
        self.enabledProfile['config']['healing']['highPriority']['swapRing']['tankRing']['hotkey'] = hotkey
        self.db.update(self.enabledProfile)

    def setSwapTankRingSlotByKey(self, slot):
        self.context['healing']['highPriority']['swapRing']['tankRing']['slot'] = slot
        self.enabledProfile['config']['healing']['highPriority']['swapRing']['tankRing']['slot'] = slot
        self.db.update(self.enabledProfile)

    def setSwapMainRingSlotByKey(self, slot):
        self.context['healing']['highPriority']['swapRing']['mainRing']['slot'] = slot
        self.enabledProfile['config']['healing']['highPriority']['swapRing']['mainRing']['slot'] = slot
        self.db.update(self.enabledProfile)

    def setSwapMainRingHotkey(self, hotkey):
        self.context['healing']['highPriority']['swapRing']['mainRing']['hotkey'] = hotkey
        self.enabledProfile['config']['healing']['highPriority']['swapRing']['mainRing']['hotkey'] = hotkey
        self.db.update(self.enabledProfile)

    def setSwapRingHpPercentageGreaterThan(self, hpPercentageGreaterThan):
        self.context['healing']['highPriority']['swapRing']['mainRing']['hpPercentageGreaterThan'] = hpPercentageGreaterThan
        self.enabledProfile['config']['healing']['highPriority']['swapRing']['mainRing'][
            'hpPercentageGreaterThan'] = hpPercentageGreaterThan
        self.db.update(self.enabledProfile)

    def setSwapAmuletHpPercentageLessThanOrEqual(self, hpPercentageLessThanOrEqual):
        self.context['healing']['highPriority']['swapAmulet']['tankAmulet']['hpPercentageLessThanOrEqual'] = hpPercentageLessThanOrEqual
        self.enabledProfile['config']['healing']['highPriority']['swapAmulet']['tankAmulet'][
            'hpPercentageLessThanOrEqual'] = hpPercentageLessThanOrEqual
        self.db.update(self.enabledProfile)

    def setSwapAmuletHpPercentageGreaterThan(self, hpPercentageGreaterThan):
        self.context['healing']['highPriority']['swapAmulet']['mainAmulet']['hpPercentageGreaterThan'] = hpPercentageGreaterThan
        self.enabledProfile['config']['healing']['highPriority']['swapAmulet']['mainAmulet'][
            'hpPercentageGreaterThan'] = hpPercentageGreaterThan
        self.db.update(self.enabledProfile)

    def setSwapTankAmuletHotkey(self, hotkey):
        self.context['healing']['highPriority']['swapAmulet']['tankAmulet']['hotkey'] = hotkey
        self.enabledProfile['config']['healing']['highPriority']['swapAmulet']['tankAmulet']['hotkey'] = hotkey
        self.db.update(self.enabledProfile)

    def setSwapMainAmuletHotkey(self, hotkey):
        self.context['healing']['highPriority']['swapAmulet']['mainAmulet']['hotkey'] = hotkey
        self.enabledProfile['config']['healing']['highPriority']['swapAmulet']['mainAmulet']['hotkey'] = hotkey
        self.db.update(self.enabledProfile)

    def setSwapTankAmuletSlotByKey(self, slot):
        self.context['healing']['highPriority']['swapAmulet']['tankAmulet']['slot'] = slot
        self.enabledProfile['config']['healing']['highPriority']['swapAmulet']['tankAmulet']['slot'] = slot
        self.db.update(self.enabledProfile)

    def setSwapMainAmuletSlotByKey(self, slot):
        self.context['healing']['highPriority']['swapAmulet']['mainAmulet']['slot'] = slot
        self.enabledProfile['config']['healing']['highPriority']['swapAmulet']['mainAmulet']['slot'] = slot
        self.db.update(self.enabledProfile)

    def setSpellHpPercentageLessThanOrEqual(self, spellType, hpPercentage):
        self.context['healing']['spells'][spellType]['hpPercentageLessThanOrEqual'] = hpPercentage
        self.enabledProfile['config']['healing']['spells'][spellType]['hpPercentageLessThanOrEqual'] = hpPercentage
        self.db.update(self.enabledProfile)

    def setSpellManaPercentageGreaterThanOrEqual(self, spellType, hpPercentage):
        self.context['healing']['spells'][spellType]['manaPercentageGreaterThanOrEqual'] = hpPercentage
        self.enabledProfile['config']['healing']['spells'][spellType]['manaPercentageGreaterThanOrEqual'] = hpPercentage
        self.db.update(self.enabledProfile)

    def setSpellName(self, spellType, spell):
        self.context['healing']['spells'][spellType]['spell'] = spell
        self.enabledProfile['config']['healing']['spells'][spellType]['spell'] = spell
        self.db.update(self.enabledProfile)

    def setHealthPotionManaPercentageGreaterThanOrEqual(self, healthPotionType, hpPercentage):
        self.context['healing']['potions'][healthPotionType]['manaPercentageGreaterThanOrEqual'] = hpPercentage
        self.enabledProfile['config']['healing']['potions'][healthPotionType]['manaPercentageGreaterThanOrEqual'] = hpPercentage
        self.db.update(self.enabledProfile)

    def setHealthPotionManaPercentageLessThanOrEqual(self, healthPotionType, hpPercentage):
        self.context['healing']['potions'][healthPotionType]['manaPercentageLessThanOrEqual'] = hpPercentage
        self.enabledProfile['config']['healing']['potions'][healthPotionType]['manaPercentageLessThanOrEqual'] = hpPercentage
        self.db.update(self.enabledProfile)

    def toggleCavebot(self, enabled):
        self.context['ng_cave']['enabled'] = enabled
        self.enabledProfile['config']['ng_cave']['enabled'] = enabled
        self.db.update(self.enabledProfile)

    def toggleRunToCreatures(self, enabled):
        self.context['ng_cave']['runToCreatures'] = enabled
        self.enabledProfile['config']['ng_cave']['runToCreatures'] = enabled
        self.db.update(self.enabledProfile)

    def toggleComboSpells(self, enabled):
        self.context['ng_comboSpells']['enabled'] = enabled
        self.enabledProfile['config']['ng_comboSpells']['enabled'] = enabled
        self.db.update(self.enabledProfile)

    def toggleHealingMaster(self, enabled):
        """Alle Heil-Funktionen gemeinsam schalten (Overlay/Dashboard)."""
        healing = self.context['healing']
        for potion in healing['potions'].values():
            potion['enabled'] = enabled
        for spell in healing['spells'].values():
            spell['enabled'] = enabled
        healing['eatFood']['enabled'] = enabled
        self.enabledProfile['config']['healing'] = healing
        self.db.update(self.enabledProfile)

    def healingMasterEnabled(self):
        """True, wenn mindestens eine Heil-Funktion aktiv ist."""
        healing = self.context['healing']
        return (
            any(p['enabled'] for p in healing['potions'].values()) or
            any(s['enabled'] for s in healing['spells'].values()) or
            healing['eatFood']['enabled']
        )

    HEALING_PRESETS = {
        'ritter': {
            'firstHealthPotion': 65, 'firstManaPotion': 0,
            'lightHealing': 70, 'criticalHealing': 45, 'utura': True,
        },
        'paladin': {
            'firstHealthPotion': 70, 'firstManaPotion': 0,
            'lightHealing': 60, 'criticalHealing': 40, 'utura': True,
        },
        'magier': {
            'firstHealthPotion': 55, 'firstManaPotion': 30,
            'lightHealing': 65, 'criticalHealing': 45, 'utura': True,
        },
    }

    def applyHealingPreset(self, name):
        """Vocations-Vorlage: Schwellen + Aktivierung in einem Schreibvorgang."""
        preset = self.HEALING_PRESETS[name]
        healing = self.context['healing']
        hp = healing['potions']['firstHealthPotion']
        hp['enabled'] = preset['firstHealthPotion'] > 0
        hp['hpPercentageLessThanOrEqual'] = preset['firstHealthPotion']
        mana = healing['potions']['firstManaPotion']
        mana['enabled'] = preset['firstManaPotion'] > 0
        mana['manaPercentageLessThanOrEqual'] = preset['firstManaPotion']
        light = healing['spells']['lightHealing']
        light['enabled'] = True
        light['hpPercentageLessThanOrEqual'] = preset['lightHealing']
        critical = healing['spells']['criticalHealing']
        critical['enabled'] = True
        critical['hpPercentageLessThanOrEqual'] = preset['criticalHealing']
        healing['spells']['utura']['enabled'] = preset['utura']
        healing['eatFood']['enabled'] = True
        self.enabledProfile['config']['healing'] = healing
        self.db.update(self.enabledProfile)

    def toggleSingleCombo(self, enabled, index):
        self.context['ng_comboSpells']['items'][index]['enabled'] = enabled
        self.enabledProfile['config']['ng_comboSpells']['items'][index]['enabled'] = enabled
        self.db.update(self.enabledProfile)

    def removeSpellByIndex(self, index, indexTable):
        self.context['ng_comboSpells']['items'][index]['spells'].pop(indexTable)
        # self.enabledProfile['config']['ng_comboSpells']['items'][index]['spells'].pop(
        #     index)
        self.db.update(self.enabledProfile)

    def changeComboName(self, name, index):
        self.context['ng_comboSpells']['items'][index]['name'] = name
        self.enabledProfile['config']['ng_comboSpells']['items'][index]['name'] = name
        self.db.update(self.enabledProfile)

    def setCompare(self, compare, index):
        self.context['ng_comboSpells']['items'][index]['creatures']['compare'] = compare
        self.enabledProfile['config']['ng_comboSpells']['items'][index]['creatures']['compare'] = compare
        self.db.update(self.enabledProfile)

    def changeCompareValue(self, value, index):
        if not value:
            return
        self.context['ng_comboSpells']['items'][index]['creatures']['value'] = int(value)
        self.enabledProfile['config']['ng_comboSpells']['items'][index]['creatures']['value'] = int(value)
        self.db.update(self.enabledProfile)

    def setComboSpellName(self, name, index, indexSecond):
        self.context['ng_comboSpells']['items'][index]['spells'][indexSecond]['name'] = name
        self.enabledProfile['config']['ng_comboSpells']['items'][index]['spells'][indexSecond]['name'] = name
        self.db.update(self.enabledProfile)

    def setComboSpellHotkey(self, key, index, indexSecond):
        self.context['ng_comboSpells']['items'][index]['spells'][indexSecond]['hotkey'] = key
        self.enabledProfile['config']['ng_comboSpells']['items'][index]['spells'][indexSecond]['hotkey'] = key
        self.db.update(self.enabledProfile)

    def toggleAutoHur(self, enabled):
        self.context['auto_hur']['enabled'] = enabled
        self.enabledProfile['config']['auto_hur']['enabled'] = enabled
        self.db.update(self.enabledProfile)

    def toggleAutoHurPz(self, enabled):
        self.context['auto_hur']['pz'] = enabled
        self.enabledProfile['config']['auto_hur']['pz'] = enabled
        self.db.update(self.enabledProfile)

    def setAutoHurHotkey(self, hotkey):
        self.context['auto_hur']['hotkey'] = hotkey
        self.enabledProfile['config']['auto_hur']['hotkey'] = hotkey
        self.db.update(self.enabledProfile)

    def setAutoHurSpell(self, spell):
        self.context['auto_hur']['spell'] = spell
        self.enabledProfile['config']['auto_hur']['spell'] = spell
        self.db.update(self.enabledProfile)

    def toggleAlert(self, enabled):
        self.context['alert']['enabled'] = enabled
        self.enabledProfile['config']['alert']['enabled'] = enabled
        self.db.update(self.enabledProfile)

    def toggleAlertCave(self, enabled):
        self.context['alert']['cave'] = enabled
        self.enabledProfile['config']['alert']['cave'] = enabled
        self.db.update(self.enabledProfile)

    def toggleAlertSayPlayer(self, enabled):
        self.context['alert']['sayPlayer'] = enabled
        self.enabledProfile['config']['alert']['sayPlayer'] = enabled
        self.db.update(self.enabledProfile)

    def toggleClearStatsPoison(self, enabled):
        self.context['clear_stats']['poison'] = enabled
        self.enabledProfile['config']['clear_stats']['poison'] = enabled
        self.db.update(self.enabledProfile)

    def setClearStatsPoisonHotkey(self, hotkey):
        self.context['clear_stats']['poison_hotkey'] = hotkey
        self.enabledProfile['config']['clear_stats']['poison_hotkey'] = hotkey
        self.db.update(self.enabledProfile)

    def toggleManaPotionsByKey(self, manaPotionType, enabled):
        self.context['healing']['potions'][manaPotionType]['enabled'] = enabled

    def setManaPotionManaPercentageLessThanOrEqual(self, manaPotionType, manaPercentage):
        self.context['healing']['potions'][manaPotionType]['manaPercentageLessThanOrEqual'] = manaPercentage

    def toggleHealingSpellsByKey(self, contextKey, enabled):
        self.context['healing']['spells'][contextKey]['enabled'] = enabled

    def setHealingSpellsHpPercentage(self, contextKey, hpPercentage):
        self.context['healing']['spells'][contextKey]['hpPercentageLessThanOrEqual'] = hpPercentage

    def setHealingSpellsHotkey(self, contextKey, hotkey):
        self.context['healing']['spells'][contextKey]['hotkey'] = hotkey


def _mergeMissing(target, defaults):
    """Fuellt fehlende Config-Schluessel aus den Defaults nach.

    Alte Profile (file.json) bekommen so neue Felder wie healing.spells
    .mediumHealing oder ng_deathConfig — vorhandene Werte bleiben
    unangetastet. Rueckgabe: True, wenn sich etwas geaendert hat.
    """
    changed = False
    for key, value in defaults.items():
        if key not in target:
            target[key] = deepcopy(value)
            changed = True
        elif isinstance(value, dict) and isinstance(target.get(key), dict):
            changed = _mergeMissing(target[key], value) or changed
    return changed
