from ops import *

def snapshot(label):
    rows=api('/api/v1/streams')['streams']
    safe=[{k:r.get(k) for k in ('stream_id','state','child_pid','cleanup_pending','run_id')} for r in rows]
    save('resume-'+label+'.json',safe)
    assert all(r['state']=='stopped' and not r.get('child_pid') and not r.get('cleanup_pending') for r in rows),'CHANNEL_NOT_STOPPED_'+label
    return rows

assert not (HERE/'resume-intent.json').exists(),'Use resume evidence; do not repeat'
image=json.loads((HERE/'image.json').read_text())
intent=json.loads((HERE/'reflect-intent.json').read_text())
assert cmd(['git','-C',str(REPO),'rev-parse','HEAD']).strip()=='b8a53e0f359a484adf336f533be908bb87894883'
assert not cmd(['git','-C',str(REPO),'status','--porcelain']).strip()
assert json.loads(cmd(compose()+['config','--format','json']))==json.loads((PRIVATE/'compose-after.json').read_text())
assert shutil.disk_usage('/').free>15*1024**3
for p,h in json.loads((HERE/'build-intent.json').read_text())['hashes'].items():
    assert hashlib.sha256((REPO/p).read_bytes()).hexdigest()==h
before={n:inspect(n) for n in cmd(['docker','ps','-a','--format','{{.Names}}']).splitlines()}
assert before['contextra-analytics-1']['Image']==image['id']
for n in ('contextra-analytics-1','contextra-ai-gateway-1'):
    assert not before[n]['State']['Running'] and before[n]['State']['ExitCode']==0
baseline=ledger();assert not baseline['reservations']
save('resume-intent.json',dict(image=image,ledger=baseline,head='b8a53e0',started_by='user_resume_approval'))
try:
    cmd(['docker','start','contextra-analytics-1'],timeout=30)
    deadline=time.monotonic()+140
    while True:
        try:ready=api('/ready');break
        except Exception:
            if time.monotonic()>deadline:raise RuntimeError('ANALYTICS_READINESS_TIMEOUT')
            assert shutil.disk_usage('/').free>15*1024**3
            time.sleep(2)
    rows=snapshot('before-gateway')
    env=dict(x.split('=',1) for x in inspect('contextra-analytics-1')['Config']['Env'])
    assert all(env[k]==v for k,v in intent['policy'].items())
    model_script='''import urllib.request,json
print(json.dumps({m:urllib.request.urlopen("http://127.0.0.1:8000/v2/models/"+m+"/ready",timeout=3).status for m in ["RFDETRMedium","RFDETRKeypointPreview","RFDETRFireSmoke","Awiros_person_and_head_detection"]}))'''
    models=json.loads(cmd(['docker','exec','contextra-analytics-1','python3','-c',model_script]))
    settings=[]
    for r in rows:
        s=api('/api/v1/streams/'+r['stream_id']+'/settings')['configured']
        settings.append(dict(stream_id=r['stream_id'],fall_person=s['fall']['person_score'],
            fall_joint=s['fall']['joint_score'],fall_down=s['fall']['down_angle_deg'],
            skip_hold=s['fall']['test_skip_down_hold'],fight_person=s['fight']['person_score'],
            fight_joint=s['fight']['joint_score'],fight_bursts=s['fight']['required_bursts']))
    artifacts=api('/api/v1/metadata/status')['artifacts']
    assert artifacts['enabled'] and artifacts['http_enabled']
    cmd(['docker','start','contextra-ai-gateway-1'],timeout=30)
    cmd(['docker','exec','contextra-ai-gateway-1','nginx','-t','-c','/tmp/nginx.conf'])
    bridge_script='''import urllib.request,json,os
from pathlib import Path
r=urllib.request.Request("http://localhost:8080/internal/bridge-status",headers={"Authorization":"Bearer "+Path(os.environ["CONTEXTRA_CONTROL_TOKEN_FILE"]).read_text().strip()})
b=json.load(urllib.request.urlopen(r,timeout=3))
print(json.dumps({"wss":{k:v for k,v in b["wss"].items() if k in ("connected","active","counts","actions","lastError")}}))'''
    deadline=time.monotonic()+90
    while True:
        bridge=json.loads(cmd(['docker','exec','contextra-ai-control-sidecar-1','python3','-c',bridge_script]))
        if bridge['wss'].get('connected') or bridge['wss'].get('active'):break
        if time.monotonic()>deadline:raise RuntimeError('WSS_RECONNECT_TIMEOUT')
        time.sleep(3)
    snapshot('after-gateway')
    time.sleep(5)
    snapshot('final')
    assert ledger()==baseline,'Ledger changed during idle resume'
    for n,c in before.items():
        now=inspect(n)
        assert now['Id']==c['Id'] and now['Image']==c['Image']
        if n not in ('contextra-analytics-1','contextra-ai-gateway-1'):
            assert now['State']['StartedAt']==c['State']['StartedAt']
    save('resume-complete.json',dict(image=image,ready=ready,models=models,bridge=bridge,
        policy=intent['policy'],settings=settings,stopped=len(rows),
        artifacts={k:artifacts[k] for k in ('enabled','http_enabled')},ledger_unchanged=True,
        non_target_preserved=True,builds=0,settings_writes=0,camera_starts=0))
    print(json.dumps(dict(ready=True,image=image['tag'],models=models,wss=bridge['wss']['connected'],
        stopped=len(rows),artifact_on=True,settings_writes=0)))
except Exception as exc:
    save('resume-failed.json',dict(error=type(exc).__name__,reason=str(exc)[:180]))
    for n in ('contextra-ai-gateway-1','contextra-analytics-1'):
        if inspect(n)['State']['Running']:cmd(['docker','stop','--signal=SIGTERM','--timeout=-1',n],timeout=90)
    raise
