import json
import os
from pathlib import Path
import subprocess
import time
import urllib.request

os.umask(0o077)
HERE=Path(__file__).parent;HERE.chmod(0o700)
REPO=Path('/workspace/contextra-analytics-runtime-lifecycle-refactor')
PRIVATE=Path('/workspace/contextra-runtime-config')
def save(name,value):
    with (HERE/name).open('x') as f:json.dump(value,f,indent=2)
def cmd(args,timeout=30):
    result=subprocess.run(args,text=True,capture_output=True,timeout=timeout)
    if result.returncode:
        save('error-'+str(time.time_ns())+'.json',dict(code=result.returncode,stdout=result.stdout,stderr=result.stderr))
        raise RuntimeError('COMMAND_FAILED; private evidence saved')
    return result.stdout
def inspect(name):return json.loads(cmd(['docker','inspect',name]))[0]
def states():
    with urllib.request.urlopen('http://127.0.0.1:35000/api/v1/streams',timeout=5) as r:
        return {s['stream_id']:{k:s.get(k) for k in ('state','child_pid','run_id','run_generation')} for s in json.load(r)['streams']}
names=['contextra-analytics-1','contextra-ai-control-sidecar-1','contextra-redis-1','contextra-postgresql-1']
before=dict(containers={n:inspect(n)['Id'] for n in names},states=states(),gateway=inspect('contextra-ai-gateway-1')['Id'])
save('before.json',before)
gateway=inspect('contextra-ai-gateway-1')
image=gateway['Image']
for policy in ('lan_public','authenticated'):
    result=cmd(['docker','run','--rm','--pull=never','--network','none','--read-only','--user','10001:10001',
        '--cap-drop','ALL','--security-opt','no-new-privileges:true','--pids-limit','24','--memory','128m','--cpus','0.5',
        '--tmpfs','/tmp:size=16m,mode=1777','-e','AI_CONTROL_HOST_PORT=38443','-e','AI_ARTIFACT_ACCESS_POLICY='+policy,
        '-v',str(REPO/'docker/secure-gateway-entrypoint.sh')+':/etc/bridge/entrypoint.sh:ro',
        '-v',str(REPO/'docker/secure-gateway.conf.template')+':/etc/bridge/nginx.conf.template:ro',
        '-v',str(PRIVATE/'secure-bridge-tls')+':/run/ai-tls:ro',
        '--entrypoint','/bin/sh',image,'/etc/bridge/entrypoint.sh','--check'])
    save('nginx-check-'+policy+'.json',dict(passed=True,output=result))
envfile=PRIVATE/'web-start-candidate-20260918/candidate.env'
original=envfile.read_text();save('private-before.json',dict(path=str(envfile),content=original))
assert 'AI_ARTIFACT_ACCESS_POLICY=' not in original
temp=envfile.with_suffix('.pending');assert not temp.exists()
temp.write_text(original.rstrip()+'\nAI_ARTIFACT_ACCESS_POLICY=lan_public\n');temp.chmod(0o600)
assert envfile.read_text()==original;temp.replace(envfile)
compose=json.loads((PRIVATE/'web-start-candidate-20260918/activated-20260918.json').read_text())['compose_command']
merged=json.loads(cmd(compose+['config','--format','json']))
assert merged['services']['ai-gateway']['environment']['AI_ARTIFACT_ACCESS_POLICY']=='lan_public'
save('reflect-intent.json',dict(image=image,compose=compose,policy='lan_public'))
cmd(compose+['up','-d','--no-deps','--no-build','--pull','never','ai-gateway'],90)
actual=inspect('contextra-ai-gateway-1')
assert actual['State']['Running'] and actual['Image']==image
policy=cmd(['docker','exec','contextra-ai-gateway-1','cat','/tmp/media-access.conf'])
assert policy=='allow 192.168.50.0/24;\ndeny all;\nauth_request off;\n'
after=dict(containers={n:inspect(n)['Id'] for n in names},states=states())
assert before['containers']==after['containers']
save('reflected.json',dict(image=image,policy=policy,other_containers_preserved=True,
    channel_states_unchanged=before['states']==after['states'],after=after))
print(json.dumps(dict(reflected=True,channel_states_unchanged=before['states']==after['states'])),flush=True)
