import json
from remote import ROOT, python

EVIDENCE='/storage/contextra/maintenance/fight-r5-errors-20261101-r01'
code=r'''
import datetime,hashlib,json,os,re,subprocess
from pathlib import Path
root=Path(EVIDENCE)
assert not root.exists()
root.mkdir(mode=0o700);private=root/'private';private.mkdir(mode=0o700);shared=root/'shared';shared.mkdir(mode=0o700)
def save(path,raw):
 fd=os.open(path,os.O_WRONLY|os.O_CREAT|os.O_EXCL,0o600)
 with os.fdopen(fd,'wb') as f:f.write(raw)
def run(args,timeout=40):
 p=subprocess.run(args,capture_output=True,timeout=timeout)
 if p.returncode:raise RuntimeError('EVIDENCE_CAPTURE_COMMAND_FAILED')
 return p.stdout
rows={}
for role,name in [('analytics','contextra-ai2-analytics-1'),('sidecar','contextra-ai2-ai-control-sidecar-1'),('gateway','contextra-ai2-ai-gateway-1')]:
 r=json.loads(run(['docker','inspect',name]))[0]
 rows[role]=dict(id=r['Id'],image=r['Image'],started=r['State']['StartedAt'],running=r['State']['Running'])
 path=private/(role+'.log')
 fd=os.open(path,os.O_WRONLY|os.O_CREAT|os.O_EXCL,0o600)
 with os.fdopen(fd,'wb') as f:
  p=subprocess.run(['docker','logs','--timestamps','--tail','30000',name],stdout=f,stderr=subprocess.STDOUT,timeout=45)
 if p.returncode:raise RuntimeError('EVIDENCE_LOG_CAPTURE_FAILED')
snapshot=r"""import json,os,urllib.request
from pathlib import Path
t=Path(os.environ['CONTEXTRA_CONTROL_TOKEN_FILE']).read_text().strip()
def get(path):
 q=urllib.request.Request('http://127.0.0.1:5000'+path,headers={'Authorization':'Bearer '+t})
 with urllib.request.urlopen(q,timeout=5) as r:return json.load(r)
status=get('/internal/secure-control/runtime-status')
detail={s['cameraId']:get('/api/v1/streams/'+s['streamId']) for s in status['streams'] if s['cameraId'] in {'22','23','24','26','27','29'}}
print(json.dumps(dict(status=status,detail=detail)))
"""
raw=run(['docker','exec',rows['analytics']['id'],'python3','-B','-c',snapshot])
save(private/'snapshot.json',raw)
sanitizer=run(['docker','exec',rows['analytics']['id'],'python3','-B','-c',
 "from pathlib import Path; print(Path('/opt/contextra/contextra_trace/sanitize.py').read_text())"]).decode()
scope={};exec(compile(sanitizer,'verified-container-sanitizer','exec'),scope)
def text(value):
 value=scope['text'](value)
 value=re.sub(r'(?:https?|rtsps?|postgres(?:ql)?|redis)://[^\s\"<>]+','[URI_REDACTED]',value,flags=re.I)
 return re.sub(r'\b(?:\d{1,3}\.){3}\d{1,3}\b','[ADDRESS_REDACTED]',value)
def walk(value):
 if isinstance(value,str):return text(value)
 if isinstance(value,list):return [walk(v) for v in value]
 if isinstance(value,dict):return {k:('[REDACTED]' if scope['secret_key'](k) else walk(v)) for k,v in value.items()}
 return value
for path in private.glob('*.log'):
 save(shared/path.name,''.join(text(line) for line in path.read_text(errors='replace').splitlines(keepends=True)).encode())
save(shared/'snapshot.json',(json.dumps(walk(json.loads(raw)),indent=2)+'\n').encode())
meta=dict(captured_at=datetime.datetime.now(datetime.timezone.utc).isoformat(),containers=rows,log_tail_lines=30000,
 preservation='Private originals remain on this server only; shared files redact credentials, URIs and addresses',
 files={str(p.relative_to(root)):dict(bytes=p.stat().st_size,sha256=hashlib.sha256(p.read_bytes()).hexdigest()) for p in root.rglob('*') if p.is_file()})
save(root/'manifest.json',(json.dumps(meta,indent=2)+'\n').encode())
print(json.dumps(meta))
'''.replace('EVIDENCE',repr(EVIDENCE),1)
data=json.loads(python(code,sudo=True,timeout=180))
local=ROOT/'error-evidence';local.mkdir(mode=0o700)
(local/'manifest.json').write_text(json.dumps(data,indent=2)+'\n')
print(json.dumps(dict(remote=EVIDENCE,files={k:v['bytes'] for k,v in data['files'].items()},captured_at=data['captured_at'])))
