import http.server,http.client,json,threading,time
held=[]; armed=False; rejecting=False; rejects=0; lock=threading.Lock()
def log(s): print(time.strftime('%H:%M:%S'),s,flush=True)
class H(http.server.BaseHTTPRequestHandler):
 protocol_version='HTTP/1.1'
 def log_message(self,*a): pass
 def do_GET(self): self.go()
 def do_POST(self): self.go()
 def do_PATCH(self): self.go()
 def do_DELETE(self): self.go()
 def go(self):
  global armed,rejects,rejecting
  if self.path=='/proof/arm': armed=True; rejecting=False; rejects=0; self.reply({'armed':True}); return
  if self.path=='/proof/reject': rejecting=True; self.reply({'rejecting':True}); return
  if self.path=='/proof/release':
   armed=False
   with lock:
    for w,b in held:
     try:w.write(b);w.flush()
     except:pass
    n=len(held);held.clear()
   log('released '+str(n)+' idle events');self.reply({'released':n});return
  if self.path=='/proof/status': self.reply({'armed':armed,'rejects':rejects,'held':len(held)});return
  body=self.rfile.read(int(self.headers.get('Content-Length',0)))
  if rejecting and self.command=='POST' and ('/prompt_async' in self.path or self.path.split('?')[0].endswith('/message')):
   rejects+=1;log('503 rejected steer '+str(rejects));self.reply({'error':'Proof fixture: steer rejected'},503);return
  c=http.client.HTTPConnection('127.0.0.1',18971,timeout=600)
  headers={k:v for k,v in self.headers.items() if k.lower() not in ['host','connection','content-length']}
  c.request(self.command,self.path,body,headers);r=c.getresponse()
  self.send_response(r.status)
  for k,v in r.getheaders():
   if k.lower() not in ['transfer-encoding','connection','content-length']:self.send_header(k,v)
  if 'text/event-stream' in r.getheader('Content-Type',''):
   self.send_header('Connection','close');self.end_headers();event=b''
   try:
    while True:
     line=r.readline()
     if not line:break
     event+=line
     if line.strip()==b'':
      idle=b'"type":"session.idle"' in event or (b'"type":"session.status"' in event and b'"type":"idle"' in event)
      if armed and idle:
       with lock:held.append((self.wfile,event))
       log('held idle event')
      else:self.wfile.write(event);self.wfile.flush()
      event=b''
   except Exception as e:log(type(e).__name__)
  else:
   data=r.read();self.send_header('Content-Length',str(len(data)));self.end_headers();self.wfile.write(data)
  c.close()
 def reply(self,d,status=200):
  b=json.dumps(d).encode();self.send_response(status);self.send_header('Content-Type','application/json');self.send_header('Content-Length',str(len(b)));self.end_headers();self.wfile.write(b)
log('proxy ready');http.server.ThreadingHTTPServer(('127.0.0.1',18972),H).serve_forever()
