"""Same WSS URL and fixed PCM, reference receiver; no credentials in output."""
import asyncio,base64,hashlib,json,pathlib,re,time
import websockets
root=pathlib.Path(__file__).resolve().parent
profile=pathlib.Path('/home/lighthouse/esp32-dev/config/sdkconfig.defaults.local').read_text()
def setting(key):
    return json.loads(re.search(r'^'+key+r'=(.+)$',profile,re.M).group(1))
url=setting('CONFIG_DEVICE_LAB_CLOUD_WS_URL')
token=setting('CONFIG_DEVICE_LAB_DEVICE_TOKEN')

async def main():
    expected=(root/'deterministic-2s.pcm').read_bytes()
    result={'scope':'Linux reference on Lighthouse, different WAN path from watch','bytes_expected':len(expected),'pcm_sha256_expected':hashlib.sha256(expected).hexdigest()}
    frames=[];times=[];pcm=bytearray();started=time.perf_counter();command_time=None
    try:
        async with asyncio.timeout(60):
            async with websockets.connect(url,compression=None,proxy=None,max_size=262144,open_timeout=15) as ws:
                result['connection_ms']=(time.perf_counter()-started)*1000
                await ws.send(json.dumps(dict(type='hello',device_id='esp32s3-28848543a200',device_token=token,board='diagnostic-linux-reference',firmware='wss-reference-only',capabilities=['speech_playback','speech-settings','target-select'])))
                async for data in ws:
                    message=json.loads(data);kind=message.get('type')
                    if kind=='hello_ack':
                        result['hello_ack_ms']=(time.perf_counter()-started)*1000
                    elif kind=='speech_settings' and command_time is None:
                        command_time=time.perf_counter()
                        (root/'network-ab-command.json').write_text(json.dumps({'label':'linux-wss-reference'}))
                    elif kind=='speech_start':
                        result.update(speech_id=message['speech_id'],command_to_speech_start_ms=(time.perf_counter()-command_time)*1000)
                    elif kind=='speech_chunk':
                        now=time.perf_counter();seq=message['sequence'];chunk=base64.b64decode(message['audio'],validate=True)
                        assert seq==len(frames) and chunk==expected[seq*7056:(seq+1)*7056]
                        frames.append(seq);times.append(now);pcm.extend(chunk)
                    elif kind=='speech_end':
                        assert message['chunks']==25 and len(frames)==25 and pcm==expected
                        result.update(result='PASS',received_bytes=len(pcm),received_chunks=len(frames),sequence_contiguous=True,all_chunks_match_source=True,sha256=hashlib.sha256(pcm).hexdigest(),speech_end_chunks=message['chunks'],command_to_first_chunk_ms=(times[0]-command_time)*1000,first_to_last_chunk_ms=(times[-1]-times[0])*1000,max_chunk_gap_ms=max((b-a)*1000 for a,b in zip(times,times[1:])))
                        break
                else:
                    result.update(result='FAIL',failure='Connection ended before speech_end')
    except Exception as e:
        result.update(result='FAIL',error_class=type(e).__name__,received_bytes=len(pcm),received_chunks=len(frames))
    result['elapsed_ms']=(time.perf_counter()-started)*1000
    (root/'network-ab-linux-reference.json').write_text(json.dumps(result,indent=2))
    print(json.dumps(result),flush=True)
asyncio.run(main())
