"""L5 only. Capture conversion boundary to separate HTTP/download from L6."""
import asyncio,base64,json,os,pathlib,shlex,sys,time
from contextlib import asynccontextmanager
sys.path.insert(0,str(pathlib.Path.cwd()/'server'))
from device_gateway import speech
root=pathlib.Path('.cache/speech-diagnostics');root.mkdir(parents=True,exist_ok=True)
for line in (pathlib.Path.home()/'.config/esp32-device-gateway/gateway.env').read_text().splitlines():
 if line and not line.lstrip().startswith('#') and '=' in line:
  k,v=line.split('=',1);values=shlex.split(v,comments=True);os.environ[k.strip()]=values[0] if values else ''
async def main():
 records=[]
 for lang,text in [('zh','你好，这是语音播放链路测试。'),('en','Hello, this is a speech playback test.')]:
  rec={'language':lang,'request_start_monotonic':time.monotonic(),'model':speech.TTS_MODEL}
  original_bounded=speech.bounded_response;original_conversion=speech.audio_to_pcm
  async def bounded(client,url,**kwargs):
   stream=client.stream
   @asynccontextmanager
   async def traced(*a,**k):
    async with stream(*a,**k) as response:
     rec.update(http_status=response.status_code,content_type=response.headers.get('content-type',''),http_headers_elapsed_ms=(time.monotonic()-rec['request_start_monotonic'])*1000)
     yield response
   client.stream=traced
   try:data,ctype=await original_bounded(client,url,**kwargs)
   finally:client.stream=stream
   rec.update(response_bytes=len(data),http_download_elapsed_ms=(time.monotonic()-rec['request_start_monotonic'])*1000,response_kind='json/base64' if 'json' in ctype else 'audio/mpeg')
   if 'json' in ctype:
    envelope=json.loads(data);raw=base64.b64decode(envelope['result']['audio'],validate=True);assert raw;rec.update(base64_decode='PASS',decoded_audio_bytes=len(raw))
   return data,ctype
  async def capture(raw,**kwargs):
   assert raw;rec.update(source_audio_bytes=len(raw),conversion='intercepted; L6 not yet run')
   (root/('tts-'+lang+'.source')).write_bytes(raw)
   return raw
  speech.bounded_response=bounded;speech.audio_to_pcm=capture
  try:
   provider=speech.CloudflareMeloTTS(os.environ['GATEWAY_CF_ACCOUNT_ID'],os.environ['GATEWAY_CF_API_TOKEN'])
   data=await provider.synthesize(text,lang);assert data;rec['result']='PASS'
  except Exception as e:rec.update(result='FAIL',error_class=type(e).__name__)
  finally:speech.bounded_response=original_bounded;speech.audio_to_pcm=original_conversion
  records.append(rec);(root/'l5-download.json').write_text(json.dumps(records,indent=2));print(json.dumps(rec),flush=True)
  if rec['result']=='FAIL':raise SystemExit(1)
asyncio.run(main())
