import json
import os
import time
import uuid
from pathlib import Path


BRIDGE_ROOT = Path(os.getenv(
    'TIBIAPILOT_DESKTOP_BRIDGE_ROOT',
    Path(os.getenv('PROGRAMDATA', r'C:\ProgramData')) / 'TibiaPilotNG' / 'DesktopBridge',
))
TIBIA_WINDOW = 'Tibia'

# WICHTIG: Diese Bruecke darf KEINE Tastatur-/Mauseingabe an das Tibia-
# Fenster senden. Solche Eingaben erzeugt das Betriebssystem und sind
# damit von echten Geraeteeingaben unterscheidbar - der Weg, der schon
# einmal einen Account gekostet hat. Frueher gab es hier press/hotkey/
# write (keyWindow/writeWindow); sie wurden entfernt. Die Bruecke ist nur
# fuer Aktionen erlaubt, die keine simulierte Eingabe sind: einen Knopf
# ueber die Windows-Automation aufrufen (invoke_background), den
# Fensterbaum lesen (dump_tree) oder einen Feldwert setzen
# (set_value_background). Alle Spieleingaben laufen ueber den Arduino
# (src/utils/keyboard.py, src/utils/mouse.py).


def _request(command, timeout=1.0):
    request_id = str(uuid.uuid4())
    inbox = BRIDGE_ROOT / 'inbox'
    outbox = BRIDGE_ROOT / 'outbox'
    temporary = inbox / f'{request_id}.tmp'
    request = inbox / f'{request_id}.json'
    response = outbox / f'{request_id}.json'
    try:
        inbox.mkdir(parents=True, exist_ok=True)
        outbox.mkdir(parents=True, exist_ok=True)
        temporary.write_text(json.dumps(command), encoding='ascii')
        temporary.replace(request)
        deadline = time.monotonic() + timeout
        while time.monotonic() < deadline:
            if response.exists():
                result = json.loads(response.read_text(encoding='utf-8-sig'))
                response.unlink(missing_ok=True)
                return bool(result.get('ok'))
            time.sleep(0.02)
    except (OSError, ValueError):
        pass
    finally:
        temporary.unlink(missing_ok=True)
        request.unlink(missing_ok=True)
        response.unlink(missing_ok=True)
    return False


def invoke_background(pid, automation_id):
    return _request({
        'action': 'invokeBackground',
        'pid': int(pid),
        'automationId': automation_id,
    }, timeout=3.0)


def _request_data(command, timeout=5.0):
    request_id = str(uuid.uuid4())
    inbox = BRIDGE_ROOT / 'inbox'
    outbox = BRIDGE_ROOT / 'outbox'
    temporary = inbox / f'{request_id}.tmp'
    request = inbox / f'{request_id}.json'
    response = outbox / f'{request_id}.json'
    try:
        inbox.mkdir(parents=True, exist_ok=True)
        outbox.mkdir(parents=True, exist_ok=True)
        temporary.write_text(json.dumps(command), encoding='ascii')
        temporary.replace(request)
        deadline = time.monotonic() + timeout
        while time.monotonic() < deadline:
            if response.exists():
                result = json.loads(response.read_text(encoding='utf-8-sig'))
                response.unlink(missing_ok=True)
                return result
            time.sleep(0.02)
    except (OSError, ValueError):
        pass
    finally:
        temporary.unlink(missing_ok=True)
        request.unlink(missing_ok=True)
        response.unlink(missing_ok=True)
    return None


def dump_tree(pid):
    """Alle Edit-/Button-Elemente des Fensters (zum Entdecken von IDs)."""
    result = _request_data({'action': 'dumpTree', 'pid': int(pid)})
    if not result or not result.get('ok'):
        return []
    return (result.get('data') or {}).get('elements', [])


def set_value_background(pid, automation_id, text):
    """Textfeld im Hintergrund fuellen - ohne Fokus, ohne Klick."""
    result = _request_data({
        'action': 'setValueBackground',
        'pid': int(pid),
        'automationId': automation_id,
        'text': text,
    })
    return bool(result and result.get('ok'))
