"""Asynchroner LLM-Worker: Inferenz blockiert nie den Spiel-Loop.

LLM-Aufrufe (Chat-Antworten, Recovery-KI-Blick) dauern auf CPU
2-30 Sekunden. Synchron ausgefuehrt wuerde der komplette Loop —
inklusive Heilung — so lange einfrieren. Der Worker fuehrt die
Aufrufe in einem Daemon-Thread aus; der Loop reicht Ergebnisse
beim naechsten Tick durch.
"""
import itertools
import queue
import threading

PENDING = object()

_jobs = queue.Queue(maxsize=1)
_results = {}
_resultsLock = threading.Lock()
_worker = None
_ids = itertools.count(1)


def _run():
    while True:
        jobId, fn = _jobs.get()
        try:
            result = fn()
        except Exception:
            result = None
        with _resultsLock:
            _results[jobId] = result


def submit(fn):
    """Reicht einen Job ein; Rueckgabe Job-ID oder None (Queue voll)."""
    global _worker
    if _worker is None:
        _worker = threading.Thread(
            target=_run, name='llm-worker', daemon=True)
        _worker.start()
    jobId = next(_ids)
    try:
        _jobs.put_nowait((jobId, fn))
    except queue.Full:
        return None
    return jobId


def poll(jobId):
    """Ergebnis des Jobs, PENDING wenn noch nicht fertig."""
    with _resultsLock:
        return _results.pop(jobId, PENDING)
