import importlib.util
import json
import os
from pathlib import Path
import subprocess
import sys
import time
import re

os.umask(0o077)
R=Path(__file__).parent
s=importlib.util.spec_from_file_location('prev','/tmp/codex/ltb1021/2026-09-15_contextra-web-ready_r01/live.py')
prev=importlib.util.module_from_spec(s);s.loader.exec_module(prev)
ops=prev.ops
from rtsp_test_manager import Manager,IMAGE,mount

def save(name,value): (R/name).write_text(json.dumps(value,ensure_ascii=False,indent=2))

def gate():
    assert not (R/'plan.json').exists()
    repo=ops.REPO
    assert subprocess.check_output(['git','rev-parse','HEAD'],cwd=repo,text=True).strip()=='4b1260d9b04dcad49ada953fe874ceda1ba2a2c5'
    assert not subprocess.check_output(['git','status','--porcelain'],cwd=repo,text=True).strip()
    analytics=ops.inspect('contextra-analytics-1');assert not analytics['State']['Running']
    sender=prev.sender();assert sender['state']=='STREAMING'
    sc=next(c for c in Manager().containers() if Manager().owned(c,'sample01'))
    logs=subprocess.run(['docker','logs','--tail','120',sc['Id']],capture_output=True,text=True,timeout=8)
    (R/'sender-before.log').write_text(logs.stdout+logs.stderr)
    save('plan.json',dict(started=time.time(),budget_seconds=1200,extension_seconds=2100,sender=sender,sender_container=sc,analytics=analytics,redis=ops.inspect('contextra-redis-1'),others=ops.inventory(),caps=dict(receiver_seconds=15,helper_seconds=25,cpu=1,ram_mib=512,pids=64,gpu=0,decoded_frames=20,trace_bytes=4*1024**2,receivers_at_once=1),network=analytics['HostConfig']['NetworkMode'],config_hashes={str(p):ops.g.sha(p) for p in ops.FILES.values()}))
    save('ledger.json',dict(probes=[],ai_start=0,sender_restart=0,build=0))
    print('PASS: actual source clean; Analytics stopped; sender preserved; receiver CPU1/RAM512MiB/GPU0/15s/20frames')

def probe(label):
    assert label in ('before','after')
    assert not (R/(label+'-started.json')).exists()
    plan=json.loads((R/'plan.json').read_text());send=prev.sender()
    name='codex-ltb1021-rtsp503-'+label
    assert subprocess.run(['docker','inspect',name],capture_output=True).returncode!=0
    save(label+'-started.json',dict(at=time.time(),sender=send,name=name))
    cmd=['docker','run','--rm','--pull','never','--runtime','runc','--network',plan['network'],'--name',name,'--cpus','1','--memory','512m','--memory-swap','512m','--pids-limit','64','--cap-drop','ALL','-e','NVIDIA_VISIBLE_DEVICES=void','--entrypoint','timeout',IMAGE,'15','ffmpeg','-hide_banner','-loglevel','trace','-rtsp_transport','tcp','-i',send['uri'],'-an','-frames:v','20','-f','null','-']
    start=time.monotonic()
    try:
        p=subprocess.run(cmd,capture_output=True,text=True,timeout=25)
        text=p.stdout+p.stderr
        assert len(text.encode())<4*1024**2
        (R/(label+'.log')).write_text(text)
        relevant=[l for l in text.splitlines() if any(t in l for t in ['OPTIONS ','DESCRIBE ','SETUP ','PLAY ','RTSP/1.0','method ','frames successfully decoded','frame=','Input #0'])]
        save(label+'-result.json',dict(returncode=p.returncode,elapsed=time.monotonic()-start,lines=relevant,decoded=bool(re.search(r'20 frames successfully decoded',text)),error503='503' in text))
        ledger=json.loads((R/'ledger.json').read_text());ledger['probes'].append(label);save('ledger.json',ledger)
        print(json.dumps(dict(returncode=p.returncode,elapsed=round(time.monotonic()-start,2),lines=[re.sub(r'rtsp://\S+','<private-uri>',x) for x in relevant][-25:]),ensure_ascii=False))
    finally:
        subprocess.run(['docker','rm','-f',name],capture_output=True,timeout=8)

if __name__=='__main__':gate() if sys.argv[1]=='gate' else probe(sys.argv[1])
