import sys,asyncio,time,json,base64,wave,os
from pathlib import Path
sys.path.insert(0,'/tmp/jarvis-pr8-perf-audit/apps/desktop/pipecat/src')
from jarvis_voice_runtime.runtime import Runtime
from jarvis_voice_runtime.parakeet import ParakeetSegmentedSTT
from jarvis_voice_runtime.output import PcmBufferOutputTransport
ROOT=Path('/home/abstergo/Documents/Jarvis-pocket-migration/packages/jarvis-native-voice/resources');rows=[]
def ticks(pid):
 x=Path(f'/proc/{pid}/stat').read_text().split();return (int(x[13])+int(x[14]))/os.sysconf('SC_CLK_TCK')
async def main():
 msgs=[];done=asyncio.Event()
 def out(m):
  msgs.append(m)
  if m['type'] in ('capture-result','synthesis-result'):done.set()
 rt=Runtime(ROOT/'parakeet',pocket_root=ROOT/'pocket',output=out)
 try:
  await rt.command({'type':'listening-prepare','requestId':'prep'})
  for name,fixture in [('fixture',ROOT/'parakeet/test_wavs/en-english.wav'),('report',Path('/tmp/jarvis-pr8-perf-results/typical-0.wav'))]:
   with wave.open(str(fixture),'rb') as w:audio=w.readframes(w.getnframes());sr=w.getframerate()
   for i in range(3):
    msgs.clear();done.clear();cid=f'{name}-{i}';t=time.perf_counter()
    await rt.command({'type':'capture-start','requestId':cid,'captureId':cid,'sampleRate':sr,'channels':1,'contextualPhrases':[]});ready=(time.perf_counter()-t)*1000
    for n,offset in enumerate(range(0,len(audio),sr//50*2)):
     await rt.command({'type':'pcm','requestId':f'{cid}-{n}','captureId':cid,'sequence':n,'sampleRate':sr,'channels':1,'data':base64.b64encode(audio[offset:offset+sr//50*2]).decode()})
    t=time.perf_counter();await rt.command({'type':'capture-release','requestId':cid+'r','captureId':cid});await asyncio.wait_for(done.wait(),20)
    row={'mode':'stt-runtime','name':name,'trial':i,'readyMs':ready,'releaseMs':(time.perf_counter()-t)*1000,'audioSeconds':len(audio)/2/sr,'timing':next(m['timing'] for m in msgs if m['type']=='stt-timing'),'result':msgs[-1]};rows.append(row);print(json.dumps(row),flush=True)
  await rt._prepare_speech(remote=True)
  for trigger in (25,250,1000):
   for i in range(3):
    done.clear();msgs.clear();sid=f'cancel-{trigger}-{i}'
    await rt.command({'type':'synthesis-start','requestId':sid,'synthesisId':sid,'text':json.loads(Path('/tmp/pocket-texts.json').read_text())['long']})
    await asyncio.sleep(trigger/1000);t=time.perf_counter()
    await rt.command({'type':'synthesis-cancel','requestId':sid+'c','synthesisId':sid});await asyncio.wait_for(done.wait(),10)
    row={'mode':'cancel-runtime','triggerMs':trigger,'trial':i,'cancelMs':(time.perf_counter()-t)*1000,'terminal':next(m for m in msgs if m['type']=='synthesis-result')};rows.append(row);print(json.dumps(row),flush=True)
  pid=rt._tts.native_tts.daemon._process.pid
  before=[ticks(os.getpid()),ticks(pid)];await asyncio.sleep(2);after=[ticks(os.getpid()),ticks(pid)]
  rows.append({'mode':'idle','windowSeconds':2,'hostCpuSeconds':after[0]-before[0],'daemonCpuSeconds':after[1]-before[1]})
 finally:
  await rt.command({'type':'shutdown','requestId':'bye'});Path('/tmp/jarvis-pr8-perf-results/stt-cancel.json').write_text(json.dumps(rows,indent=2))
asyncio.run(main())
