from mcp_driver import MCP, ROOT
import sys,time,json,subprocess,os,textwrap,datetime
side=sys.argv[1]; mode=sys.argv[2] if len(sys.argv)>2 else 'original'
out=ROOT/(side+'-'+mode+'-'+datetime.datetime.now().strftime('%H%M%S')); out.mkdir()
m=MCP(side); events=[]
wid=subprocess.check_output(['xdotool','search','--name','^Preview timeout proof$']).decode().splitlines()[-1]
subprocess.run(['xdotool','windowmove',wid,'0','0','windowsize',wid,'1920','1080'],check=True)
print('\033[?25l',end='',flush=True)
time.sleep(0.6)
rec=subprocess.Popen(['ffmpeg','-y','-loglevel','error','-f','x11grab','-video_size','1920x1080','-framerate','10','-i',os.environ['DISPLAY'],'-c:v','libx264','-preset','ultrafast','-crf','22','-pix_fmt','yuv420p',str(out/'terminal.mp4')],stdin=subprocess.PIPE)
start=time.monotonic()
def scene(title):
 print('\033[2J\033[H',end=''); print(('BEFORE | BASE 2c61677d59' if side.endswith('base') else 'AFTER | HEAD 60711a12e1')+' | '+mode)
 print('Linux | actual T3 server | '+('Electron desktop preview' if side.startswith('desktop-') else 'headless Chromium preview')+' | synthetic HTTP page')
 print('1280 x 800 preview | same driver and fresh isolated database per commit\n')
 print(title+'\n'+'='*100,flush=True)
def call(name,args,description=None):
 print('\n> '+(description or name+' '+json.dumps(args)),flush=True)
 t=time.monotonic(); r=m.call(name,args); elapsed=time.monotonic()-t
 events.append({'tool':name,'arguments':args,'durationSeconds':round(elapsed,3),'response':r})
 print('Returned in %.3f seconds'%elapsed,flush=True)
 if r.get('isError'): value='\n'.join(c.get('text','') for c in r.get('content',[]))
 else:
  v=r.get('structuredContent',r)
  if name=='preview_open': value=json.dumps({k:v.get(k) for k in ['available','visible','url','title','loading']},indent=2)
  elif name=='preview_snapshot': value=json.dumps({k:v.get(k) for k in ['url','title','loading','accessibilityTree','screenshot']},indent=2); value=value[:2400]
  else: value=json.dumps(v,indent=2)
 for l in value.splitlines(): print(textwrap.fill(l,width=108,replace_whitespace=False),flush=True)
 return r
try:
 scene('1. Open the local fixture')
 r=call('preview_open',{'url':'http://127.0.0.1:18765/'+('iframe.html' if mode=='iframe' else 'index.html'),'open':side.startswith('desktop-'),'reuseExistingTab':False})
 tab=r['structuredContent']['tabId']; target={'tabId':tab}
 if mode=='iframe':
  scene('2. Arm cross-site child: its returned value array becomes an unanswered thenable')
  print('Child page installs Array.prototype.then = function(resolve, reject) {}. Real browser, no mocks.',flush=True)
  call('preview_evaluate',{**target,'expression':'document.querySelector("iframe").contentWindow.postMessage("arm", "*"); "armed"'})
  time.sleep(0.4)
 elif mode=='original':
  scene('2. Schedule a 25-second page loop, then snapshot immediately')
  call('preview_evaluate',{**target,'expression':'setTimeout(() => { const end = Date.now() + 25000; while (Date.now() < end) {} }, 300); "scheduled"'})
 elif mode=='page-state':
  scene('2. Install a page innerText getter that occupies the renderer during page-state capture')
  call('preview_evaluate',{**target,'expression':'Object.defineProperty(document.body, "innerText", { configurable: true, get() { const end=Date.now()+25000; while(Date.now()<end){}; return "Preview timeout proof"; } }); "installed"'})
 if mode=='original': time.sleep(0.4)
 scene('3. Snapshot timeout: compare reported deadline and pending work')
 call('preview_snapshot',target)
 time.sleep(3)
 subprocess.run(['import','-window','root',str(out/'snapshot-timeout.png')],check=True)
 time.sleep(0.5)
 subprocess.run(['import','-window','root',str(out/'snapshot-timeout-stable.png')],check=True)
 scene('4. Evaluate a 30-second promise: the evaluate budget remains 15000ms')
 call('preview_evaluate',{**target,'expression':'await new Promise(resolve => setTimeout(() => resolve("late"), 30000))'})
 time.sleep(3)
 if mode=='iframe':
  scene('5. Restore child frame value results')
  call('preview_evaluate',{**target,'expression':'document.querySelector("iframe").contentWindow.postMessage("restore", "*"); "restored"'})
  time.sleep(0.4)
 if mode=='page-state':
  scene('5. Restore ordinary page text')
  call('preview_evaluate',{**target,'expression':'delete document.body.innerText; "restored"'})
 scene('6. Recovery: take another snapshot on the SAME tab')
 call('preview_snapshot',target)
 print('\nCOMPLETE: snapshot error, 15000ms evaluate check, and recovery are all recorded.',flush=True)
 time.sleep(4)
 subprocess.run(['import','-window','root',str(out/'recovery.png')],check=True)
 call('t3_preview_close',target)
finally:
 (out/'transcript.json').write_text(json.dumps(events,indent=2))
 rec.stdin.write(b'q');rec.stdin.flush();rec.wait()
 (ROOT/(side+'-'+mode+'-last.txt')).write_text(str(out))
