from ops import *
import yaml,sys
promoted=len(sys.argv)>1 and sys.argv[1]=='promoted'

rows=api('/api/v1/streams')['streams']
assert all(r['state']=='stopped' and not r.get('child_pid') and not r.get('cleanup_pending') and
    not any(v.get('child_pid') for v in r.get('provider_processes',{}).values()) for r in rows)
before=yaml.safe_load((PRIVATE/'runtime-original.yaml').read_text())
saved=json.loads((PRIVATE/'settings-baseline.json').read_text());deltas=[]
for camera, original in saved.items():
    spec=next(s for s in before['added'] if str(s.get('camera_id'))==camera)
    current=api('/api/v1/streams/'+spec['stream_id']+'/settings')['configured']
    a={k:v for k,v in original.items() if k!='revision'}
    b={k:v for k,v in current.items() if k!='revision'}
    if 'scenario' not in a['fire'] and 'scenario' in b['fire']:
        assert b['fire']['scenario']['enabled'] is False
        del b['fire']['scenario'];deltas.append(camera)
    assert a==b,camera
image=json.loads((HERE/('reflect-promoted-done.json' if promoted else 'reflect-final-done.json')).read_text())['image']
expected=json.loads((PRIVATE/'compose-before.json').read_text())
expected['services']['analytics']['image']=image['id']
if promoted: expected['services']['analytics']['environment']['CONTEXTRA_SOURCE_LATEST_TRIAL']='true'
assert json.loads(cmd(compose()+['config','--format','json']))==expected
env=dict(s.split('=',1) for s in inspect('contextra-analytics-1')['Config']['Env'])
flags=dict(CONTEXTRA_PROVIDER_LINEAR_TRIAL='true',CONTEXTRA_PROVIDER_FRESHNESS_ENABLED='false',
 CONTEXTRA_TEST_NO_CAPTURE='false',CONTEXTRA_SOURCE_LATEST_TRIAL='false',
 CONTEXTRA_INPUT_TIMING_SECONDS='0',CONTEXTRA_PIPELINE_DIAGNOSTICS='false',
 CONTEXTRA_COMPLETED_QUEUE_MAX_AGE_SECONDS='1',CONTEXTRA_EVENT_COOLDOWN_SECONDS='10',
 CONTEXTRA_METADATA_STREAM_LENGTH='300')
if promoted: flags['CONTEXTRA_SOURCE_LATEST_TRIAL']='true'
assert all(env.get(k)==v for k,v in flags.items()),{k:env.get(k) for k in flags}
defaults=dict(CONTEXTRA_TEST_NO_CAPTURE='false',CONTEXTRA_SOURCE_LATEST_TRIAL='false',
 CONTEXTRA_INPUT_TIMING_SECONDS='0',CONTEXTRA_PIPELINE_DIAGNOSTICS='false')
persistent=expected['services']['analytics']['environment']
assert all(str(persistent.get(k,defaults.get(k)))==v for k,v in flags.items())
base=json.loads((HERE/'baseline.json').read_text());non_target=[]
for name,old in base['containers'].items():
    if name in ('contextra-analytics-1','contextra-ai-gateway-1'):continue
    c=inspect(name)
    if c['Id']!=old['id'] or c['Image']!=old['image'] or c['State']['StartedAt']!=old['started']:
        non_target.append(dict(name=name,id_same=c['Id']==old['id'],image_same=c['Image']==old['image'],
                              started_before=old['started'],started_now=c['State']['StartedAt']))
models=json.loads(cmd(['docker','exec','contextra-analytics-1','python3','-B','-c',
 '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"]}))']))
assert all(v==200 for v in models.values())
if promoted:
    assert not inspect('contextra-ai-gateway-1')['State']['Running']
else:
    cmd(['docker','start','contextra-ai-gateway-1'],timeout=30)
code='''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()})
print(json.dumps(json.load(urllib.request.urlopen(r,timeout=3))))'''
deadline=time.monotonic()+40
while True:
    bridge=json.loads(cmd(['docker','exec','contextra-ai-control-sidecar-1','python3','-B','-c',code],timeout=6))
    if bool(bridge['wss']['connected'])==(not promoted) or time.monotonic()>deadline:break
    time.sleep(2)
a=api('/api/v1/metadata/status')['artifacts']
rows=api('/api/v1/streams')['streams']
save('final-state-promoted.json' if promoted else 'final-state.json',dict(image=image,models=models,
 states={s:sum(r['state']==s for r in rows) for s in set(r['state'] for r in rows)},
 children=sum(bool(r.get('child_pid'))+sum(bool(v.get('child_pid')) for v in r.get('provider_processes',{}).values()) for r in rows),
 gateway='stopped_for_next_trial' if promoted else 'running',wss=bridge['wss']['connected'],flags=flags,
 artifact={k:a[k] for k in ('enabled','http_enabled')},training=training(),settings_restored=True,
 inactive_fire_defaults_materialized=deltas,non_target_operated_by_task=False,non_target_drift=non_target,
 compose_changes=['image','source_latest=true'] if promoted else ['image'],persistent_effective_defaults_match=True,
 gpu=cmd(['nvidia-smi','--query-gpu=memory.used,utilization.gpu','--format=csv,noheader']).strip()))
print(json.dumps(dict(image=image['tag'],states={s:sum(r['state']==s for r in rows) for s in set(r['state'] for r in rows)},
 wss=bridge['wss']['connected'],non_target_drift=non_target)))
