import json

from src.gameplay import webcommands


class _UiContext:
    def __init__(self):
        self.context = {'ng_pause': True, 'window': object()}
        self.calls = []

    def pause(self):
        self.calls.append('pause')
        self.context['ng_pause'] = True

    def toggleCavebot(self, value):
        self.calls.append(('toggleCavebot', value))

    def toggleRunToCreatures(self, value):
        self.calls.append(('toggleRunToCreatures', value))

    def toggleHealingMaster(self, value):
        self.calls.append(('toggleHealingMaster', value))

    def toggleComboSpells(self, value):
        self.calls.append(('toggleComboSpells', value))


def _command(tmp_path, payload, monkeypatch):
    target = tmp_path / 'cmd.json'
    target.write_text(json.dumps(payload), encoding='utf-8')
    monkeypatch.setattr(webcommands, 'COMMAND_FILE', target)
    return target


def test_no_command_noop(tmp_path, monkeypatch):
    monkeypatch.setattr(
        webcommands, 'COMMAND_FILE', tmp_path / 'fehlt.json')
    ui = _UiContext()

    webcommands.consumeWebCommand(ui)

    assert ui.calls == []


def test_pause_command(tmp_path, monkeypatch):
    _command(tmp_path, {'action': 'pause'}, monkeypatch)
    ui = _UiContext()

    webcommands.consumeWebCommand(ui)

    assert ui.calls == ['pause']
    # Datei wurde konsumiert (geloescht).
    assert not (tmp_path / 'cmd.json').exists()


def test_toggle_command_with_value(tmp_path, monkeypatch):
    _command(tmp_path, {'action': 'toggleCavebot', 'value': True}, monkeypatch)
    ui = _UiContext()

    webcommands.consumeWebCommand(ui)

    assert ui.calls == [('toggleCavebot', True)]


def test_broken_command_file_is_tolerated(tmp_path, monkeypatch):
    target = tmp_path / 'cmd.json'
    target.write_text('{kaputt', encoding='utf-8')
    monkeypatch.setattr(webcommands, 'COMMAND_FILE', target)
    ui = _UiContext()

    webcommands.consumeWebCommand(ui)

    assert ui.calls == []
    assert not target.exists()


def test_unknown_action_ignored(tmp_path, monkeypatch):
    _command(tmp_path, {'action': 'quatsch'}, monkeypatch)
    ui = _UiContext()

    webcommands.consumeWebCommand(ui)

    assert ui.calls == []


def test_set_config_writes_context_and_profile(tmp_path, monkeypatch):
    _command(tmp_path, {
        'action': 'setConfig', 'path': 'ng_deathConfig.refillCap',
        'value': 55}, monkeypatch)
    ui = _UiContext()
    ui.enabledProfile = {'config': {'ng_deathConfig': {'refillCap': 30}}}
    ui.db = type('Db', (), {'update': lambda self, doc: ui.calls.append('db')})()

    webcommands.consumeWebCommand(ui)

    assert ui.context['ng_deathConfig']['refillCap'] == 55
    assert ui.enabledProfile['config']['ng_deathConfig']['refillCap'] == 55
    assert 'db' in ui.calls


def test_set_config_rejects_non_whitelisted_path(tmp_path, monkeypatch):
    _command(tmp_path, {
        'action': 'setConfig', 'path': 'ng_radar.hack', 'value': 'x'},
        monkeypatch)
    ui = _UiContext()
    ui.enabledProfile = {'config': {}}
    ui.db = type('Db', (), {'update': lambda self, doc: ui.calls.append('db')})()

    webcommands.consumeWebCommand(ui)

    assert 'ng_radar' not in ui.context
    assert 'ng_radar' not in ui.enabledProfile['config']


def test_set_config_creates_nested_path(tmp_path, monkeypatch):
    _command(tmp_path, {
        'action': 'setConfig', 'path': 'healing.eatFood.enabled',
        'value': True}, monkeypatch)
    ui = _UiContext()
    ui.enabledProfile = {'config': {'healing': {}}}
    ui.db = type('Db', (), {'update': lambda self, doc: None})()

    webcommands.consumeWebCommand(ui)

    assert ui.context['healing']['eatFood']['enabled'] is True
