"""Temporary runtime wrapper; no endpoint and no credential/payload logging."""
import asyncio, base64, hashlib, importlib, json, pathlib, sys, time
from contextlib import asynccontextmanager

ROOT = pathlib.Path(__file__).resolve().parent
sys.path.insert(0, '/home/lighthouse/esp32-dev/.cache/watch-codex-quota-startup/server')
gateway = importlib.import_module('device_gateway.app')
app = gateway.app
original_lifespan = app.router.lifespan_context
original_send = gateway.speeches.send
stream_hashes = {}

def record(**fields):
    fields.update(wall_ns=time.time_ns(), mono_ns=time.monotonic_ns())
    with (ROOT/'network-ab-send.jsonl').open('a') as stream:
        stream.write(json.dumps(fields)+'\n')

async def traced_send(device, frame):
    kind = frame.get('type', '')
    if not kind.startswith('speech_'):
        return await original_send(device, frame)
    info = dict(type=kind, speech_id=frame.get('speech_id'), sequence=frame.get('sequence'))
    sid = frame.get('speech_id')
    if kind == 'speech_start':
        stream_hashes[sid] = [hashlib.sha256(), 0]
    if kind=='speech_chunk':
        raw=base64.b64decode(frame['audio'],validate=True)
        seq=frame['sequence']
        known=(ROOT/'deterministic-2s.pcm').read_bytes()[seq*7056:(seq+1)*7056]
        info.update(pcm_bytes=len(raw),pcm_sha256=hashlib.sha256(raw).hexdigest(),matches_fixed_source=(raw==known))
        state = stream_hashes[sid]
        state[0].update(raw)
        state[1] += len(raw)
    if kind == 'speech_end' and sid in stream_hashes:
        state = stream_hashes.pop(sid)
        record(event='stream_pcm', speech_id=sid, bytes=state[1], sha256=state[0].hexdigest())
    record(event='send_begin', **info)
    began = time.monotonic_ns()
    try:
        await original_send(device, frame)
    except BaseException as error:
        record(event='send_error', error=type(error).__name__, elapsed_ms=(time.monotonic_ns()-began)/1e6, **info)
        raise
    record(event='send_complete', elapsed_ms=(time.monotonic_ns()-began)/1e6, **info)

gateway.speeches.send = traced_send

async def watch_commands():
    command = ROOT/'network-ab-command.json'
    while True:
        await asyncio.sleep(.1)
        if not command.exists():
            continue
        options = json.loads(command.read_text())
        command.unlink()
        device = gateway.devices.get('esp32s3-28848543a200')
        if device is None or not device.online or not gateway.speeches.capable(device):
            record(event='not_ready')
            continue
        provider = gateway.speeches.provider
        class DiagnosticPCM:
            async def synthesize(self, text, language):
                pcm = await provider.synthesize(text, language) if options.get('tts') else (ROOT/'deterministic-2s.pcm').read_bytes()
                record(event='source', label=options.get('label','network-ab'), tts=bool(options.get('tts')), bytes=len(pcm), sha256=hashlib.sha256(pcm).hexdigest(), chunks=(len(pcm)+7055)//7056)
                return pcm
        gateway.speeches.provider = DiagnosticPCM()
        try:
            if not gateway.speeches.start(device, 'screen', '语音播放测试成功。' if options.get('tts') else 'Fixed PCM WSS diagnostic'):
                record(event='start_rejected')
                continue
            playback = gateway.speeches.active[device.connection_id]
            await playback.task
            record(event='manager_finished', speech_id=playback.speech_id)
        finally:
            gateway.speeches.provider = provider

@asynccontextmanager
async def lifespan(instance):
    async with original_lifespan(instance):
        task = asyncio.create_task(watch_commands())
        record(event='wrapper_ready')
        try:
            yield
        finally:
            task.cancel()
            await asyncio.gather(task, return_exceptions=True)

app.router.lifespan_context = lifespan
if __name__ == '__main__':
    import uvicorn
    uvicorn.run(app, ws_max_size=8192, host='127.0.0.1', port=18081)
