import datetime, hashlib, http.server, json, pathlib, threading, urllib.request

ROOT=pathlib.Path(__file__).resolve().parent
PRIVATE=ROOT/'private'; RECORDS=ROOT/'records'
PRIVATE.mkdir(exist_ok=True); RECORDS.mkdir(exist_ok=True)
CONTRACT=json.loads((ROOT/'original-case-contract-v1.json').read_text(encoding='utf-8'))
ALIAS='uagentkit-qwen2.5-coder-1.5b-q4km'
UPSTREAM='http://127.0.0.1:36280'
with urllib.request.urlopen(UPSTREAM+'/v1/models',timeout=20) as r: MODELS=r.read()
(ROOT/'existing-models-v1.json').write_bytes(MODELS)
MODEL=json.loads(MODELS)['data'][0]['id']
STATE_PATH=PRIVATE/'recorder-state.json'
LOCK=threading.RLock()
STATE=json.loads(STATE_PATH.read_text()) if STATE_PATH.exists() else {'cases':{c['id']:{'attempts':0,'forwards':0,'completed':False} for c in CONTRACT['cases']},'metadataRequests':0,'deniedRequests':0,'externalProxyRequests':0}
def utc(): return datetime.datetime.now(datetime.timezone.utc).isoformat()
def save(): STATE_PATH.write_text(json.dumps(STATE,indent=2)+'\n',encoding='utf-8')
def record(name,raw):
    with (RECORDS/name).open('xb') as f: f.write(raw)
def jbytes(x): return (json.dumps(x,ensure_ascii=False,indent=2)+'\n').encode('utf-8')
save()
class Bridge(http.server.BaseHTTPRequestHandler):
    def log_message(self,*args): pass
    def reply(self,status,raw,ctype='application/json'):
        self.send_response(status); self.send_header('Content-Type',ctype); self.send_header('Content-Length',str(len(raw))); self.end_headers(); self.wfile.write(raw)
    def do_GET(self):
        if self.path in ['/v1/models','/models']:
            with LOCK: STATE['metadataRequests']+=1; save()
            self.reply(200,jbytes({'object':'list','data':[{'id':ALIAS,'object':'model','owned_by':'task-local'}]}))
        else: self.reply(404,b'{}')
    def do_POST(self):
        raw=self.rfile.read(int(self.headers.get('Content-Length',0)))
        value=json.loads(raw)
        users=[m for m in value.get('messages',[]) if m.get('role')=='user']
        text=users[-1].get('content') if users else None
        if isinstance(text,list): text=''.join(p.get('text','') for p in text if p.get('type')=='text')
        matches=[c for c in CONTRACT['cases'] if isinstance(text,str) and text.replace('\r\n','\n').strip()==c['instruction'].strip()]
        armed=(PRIVATE/'armed-case.txt').read_text().strip() if (PRIVATE/'armed-case.txt').exists() else None
        with LOCK:
            case=matches[0] if len(matches)==1 else None
            valid=bool(case and armed==case['id'] and (ROOT/'runtime-frozen-v1.json').exists() and value.get('model')==ALIAS and value.get('stream')==False and STATE['cases'][case['id']]['forwards']==0)
            if not valid:
                STATE['deniedRequests']+=1; save()
                record(f'denied-{STATE["deniedRequests"]}-request.json',raw)
                self.reply(403,jbytes({'error':{'message':'Task freeze/case/budget/payload mismatch; zero backend forward.'}})); return
            cid=case['id']; STATE['cases'][cid]['attempts']+=1; STATE['cases'][cid]['forwards']+=1; save()
            record(cid+'-native-provider-request.json',raw)
            payload=dict(value); payload['model']=MODEL
            upstream=jbytes(payload); record(cid+'-upstream-request.json',upstream)
        status=200
        try:
            with urllib.request.urlopen(urllib.request.Request(UPSTREAM+'/v1/chat/completions',data=upstream,headers={'Content-Type':'application/json'}),timeout=240) as r: answer=r.read(); status=r.status
        except Exception as error:
            answer=jbytes({'error':{'type':type(error).__name__,'message':str(error)}}); status=502
        record(cid+'-upstream-response.json',answer)
        served=answer
        equal=None
        if status==200:
            parsed=json.loads(answer); mapped=dict(parsed); mapped['model']=ALIAS; served=jbytes(mapped); equal=parsed.get('choices')==mapped.get('choices')
        record(cid+'-served-response.json',served)
        with LOCK:
            STATE['cases'][cid].update({'completed':status==200,'status':status,'choiceContentUnchanged':equal,'completedAt':utc()}); save()
        record(cid+'-receipt.json',jbytes({'caseId':cid,'at':utc(),'status':status,'modelFieldOnlyMapped':True,'choiceContentUnchanged':equal,'nativeRequestSha256':hashlib.sha256(raw).hexdigest(),'upstreamResponseSha256':hashlib.sha256(answer).hexdigest(),'servedResponseSha256':hashlib.sha256(served).hexdigest()}))
        self.reply(status,served)
class DenyProxy(http.server.BaseHTTPRequestHandler):
    def log_message(self,*args): pass
    def deny(self):
        with LOCK:
            STATE['externalProxyRequests']+=1; save()
            record(f'external-denied-{STATE["externalProxyRequests"]}.json',jbytes({'at':utc(),'method':self.command,'target':self.path,'forwarded':False}))
        self.send_response(403); self.send_header('Content-Length','0'); self.end_headers()
    do_GET=do_POST=do_CONNECT=deny
threading.Thread(target=http.server.ThreadingHTTPServer(('127.0.0.1',37422),DenyProxy).serve_forever,daemon=True).start()
(ROOT/'recorder-started-v1.json').write_bytes(jbytes({'at':utc(),'bridgePort':37421,'denyProxyPort':37422,'generationsOnStartup':0,'upstreamModelMetadataSha256':hashlib.sha256(MODELS).hexdigest()}))
http.server.ThreadingHTTPServer(('127.0.0.1',37421),Bridge).serve_forever()
