import json
from remote import ROOT, python

code=r'''
import hashlib,json,os,subprocess
from pathlib import Path
root=Path('/storage/contextra/maintenance/fight-r5-errors-20261101-r01')
snapshot=json.loads((root/'private/snapshot.json').read_text())
windows=[]
for camera,d in snapshot['detail'].items():
 for e in d['last_cleanup']['diagnostic']['events']:
  if e['name'] in ('start_requested','first_child_error'):
   windows.append(dict(camera=camera,event=e['name'],wall_ms=e['wall_ms']))
query=r"""import datetime,json,os,psycopg2
windows=WINDOWS
rows=[]
conn=psycopg2.connect(os.environ['DATABASE_URL'],connect_timeout=3,
 options='-c statement_timeout=3000 -c default_transaction_read_only=on')
with conn:
 with conn.cursor() as cur:
  for w in windows:
   t=datetime.datetime.fromtimestamp(w['wall_ms']/1000,datetime.timezone.utc)
   cur.execute('SELECT seq,doc-\'requestBody\' AS doc FROM contextra_trace_records WHERE server=%s AND camera_id=%s AND recorded_at BETWEEN %s AND %s ORDER BY seq LIMIT 100',
      (os.environ['CONTEXTRA_TRACE_SERVER'],w['camera'],t-datetime.timedelta(seconds=5),t+datetime.timedelta(seconds=5)))
   values=[dict(seq=x[0],doc=x[1]) for x in cur.fetchall()]
   rows.append(dict(window=w,rows=values,limit=100))
conn.close()
print(json.dumps(rows))
""".replace('WINDOWS',repr(windows))
p=subprocess.run(['docker','exec','contextra-ai2-analytics-1','python3','-B','-c',query],capture_output=True,timeout=60)
if p.returncode:raise RuntimeError('TRACE_READ_ONLY_QUERY_FAILED '+p.stderr.decode()[-600:])
raw=p.stdout
fd=os.open(root/'private/trace_windows.json',os.O_WRONLY|os.O_CREAT|os.O_EXCL,0o600)
with os.fdopen(fd,'wb') as f:f.write(raw)
# The existing records already mask authentication. Remove all URI/address text for sharing too.
import re
value=raw.decode()
value=re.sub(r'(?:https?|rtsps?|postgres(?:ql)?|redis)://[^\s\"<>]+','[URI_REDACTED]',value,flags=re.I)
value=re.sub(r'\b(?:\d{1,3}\.){3}\d{1,3}\b','[ADDRESS_REDACTED]',value)
fd=os.open(root/'shared/trace_windows.json',os.O_WRONLY|os.O_CREAT|os.O_EXCL,0o600)
with os.fdopen(fd,'w') as f:f.write(value)
manifest={str(p.relative_to(root)):dict(bytes=p.stat().st_size,sha256=hashlib.sha256(p.read_bytes()).hexdigest()) for p in (root/'private/trace_windows.json',root/'shared/trace_windows.json')}
(root/'trace_manifest.json').write_text(json.dumps(manifest,indent=2));(root/'trace_manifest.json').chmod(0o600)
print(json.dumps(dict(counts=[dict(window=x['window'],records=len(x['rows']),limit_reached=len(x['rows'])==100) for x in json.loads(raw)],manifest=manifest)))
'''
data=json.loads(python(code,sudo=True,timeout=90))
(ROOT/'error-evidence/trace_manifest.json').write_text(json.dumps(data,indent=2)+'\n')
shared=python("from pathlib import Path; print(Path('/storage/contextra/maintenance/fight-r5-errors-20261101-r01/shared/trace_windows.json').read_text())",sudo=True)
(ROOT/'error-evidence/shared/trace_windows.json').write_bytes(shared)
print(json.dumps(data['counts']))
