"""Fresh AI2 installation inputs. No login, service start, or old data mutation."""
import hashlib
import json
import os
from pathlib import Path
import secrets
import shutil
import socket
import subprocess
import sys
import tarfile

STAGE = Path('/storage/contextra/deploy/ai2-20261006-r01')
SOURCE = Path('/workspace/contextra/source/4f0bd4e')
SITE = Path('/storage/contextra/site/ai2-20261006-r01')
DATA = Path('/storage/contextra')
AI = '192.168.30.52'
WEB = '192.168.30.18'
PROJECT = 'contextra-ai2'
UUID = 'e49118da-66c6-49c3-b180-1d9146742b0e'

def put(path, value, mode=0o600):
    path.parent.mkdir(parents=True, exist_ok=True, mode=0o700)
    with path.open('xb') as f:
        f.write(value if isinstance(value, bytes) else value.encode())
    path.chmod(mode)

def dump(path, value, mode=0o600):
    put(path, json.dumps(value, indent=2)+'\n', mode)

def bind(source, target, readonly=False):
    return dict(type='bind', source=str(source), target=target, read_only=readonly,
                bind={'create_host_path':False})

def main():
    os.umask(0o077)
    assert os.geteuid()==0
    assert socket.gethostname()=='icertirnd-ai'
    assert shutil.disk_usage('/').free>=15*1024**3
    assert subprocess.check_output(['findmnt','-n','-o','UUID','-T','/storage']).decode().strip()==UUID
    assert not SITE.exists(), 'Existing installation inputs preserved'
    assert not subprocess.check_output(['docker','ps','-aq','--filter','label=com.docker.compose.project='+PROJECT]).strip()
    assert not Path('/etc/contextra-maintenance/server.json').exists()
    archive=STAGE/'source-4f0bd4e.tar.gz'
    assert hashlib.sha256(archive.read_bytes()).hexdigest()=='b1b3299fca8a67a08c36881610b0a7dd7ed1c27d8b6737f8db786a2b4f41069d'
    if not SOURCE.exists():
        SOURCE.mkdir(parents=True,mode=0o755)
        with tarfile.open(archive) as tar:
            tar.extractall(SOURCE,filter='data')
    SITE.mkdir(parents=True,mode=0o700)
    for name in ('configs','bridge','tls','bridge-session','redis'):
        (SITE/name).mkdir(mode=0o700)
    for name in ('artifacts','training','runtime','models/triton'):
        (DATA/name).mkdir(parents=True,exist_ok=True,mode=0o700)
    for name in ('system_config.yaml','camera_ptz_config.yaml','streams.yaml'):
        raw=(SOURCE/'configs'/name).read_bytes()
        if name=='streams.yaml':raw=b'streams: []\n'
        put(SITE/'configs'/name,raw,0o644)
    template=json.loads((SOURCE/'configs/control_templates/medium.json').read_text())
    dump(SITE/'camera-template.json',template,0o644)
    ca=(STAGE/'manager-ca.crt').read_bytes()
    assert hashlib.sha256(ca).hexdigest()=='7fbc6e255d5e42e4fb9b52ad7433de0624f45a145458e764c1018b2482277b12'
    put(SITE/'bridge/manager-ca.crt',ca,0o644)
    # Bootstrap placeholder cannot authorize Web access. Actual credentials are entered through ct.
    put(SITE/'bridge/password',secrets.token_urlsafe(40)+'\n')
    for name in ('control-token','relay-token'):
        put(SITE/'bridge'/name,secrets.token_urlsafe(40)+'\n')
    passwords={name:secrets.token_hex(24) for name in ('db','health','publisher','internal','reader')}
    acl=['user default off','user contextra_health on >'+passwords['health']+' -@all +ping',
         'user contextra_publisher on >'+passwords['publisher']+' ~contextra:metadata:v1:* -@all +@read +@write +@transaction +ping +select +client|setinfo +client|setname',
         'user contextra_internal on >'+passwords['internal']+' ~* -@all +@read +@write +@transaction +ping +select +client|setinfo +client|setname',
         'user contextra_reader on >'+passwords['reader']+' ~contextra:metadata:v1:* -@all +get +mget +hget +hgetall +xread +xrange +xrevrange +xlen +ttl +pttl +exists +type +ping +select +client|setinfo +client|setname']
    put(SITE/'redis/users.acl','\n'.join(acl)+'\n',0o640)
    put(SITE/'redis/redis.conf','bind 0.0.0.0\nprotected-mode yes\nport 6379\naclfile /usr/local/etc/redis/users.acl\nsave ""\nappendonly no\nlogfile ""\n',0o644)
    dump(SITE/'bridge/login-body.json',dict(loginId='AI-01',advertisedIp=AI,controlPort=38443,
        redis=dict(host=AI,port=16379,db=0,username='contextra_reader',password=passwords['reader'],tls=False),
        bboxStreamKey='contextra:metadata:v1:channels',connectionConfigVersion=1,aiControlCa=ca.decode()))
    images=json.loads((STAGE/'assets/manifest.json').read_text())['images']
    env=dict(CONTEXTRA_IMAGE=images['analytics'],ANALYTICS_RESTART_POLICY='no',INFRA_RESTART_POLICY='no',
        GPU_DEVICE_ID='0',POSTGRES_USER='contextra',POSTGRES_DB='contextra',POSTGRES_PASSWORD=passwords['db'],
        GRAFANA_ADMIN_PASSWORD=secrets.token_hex(24),CONTEXTRA_CONFIG_ROOT=str(SITE),
        CONTEXTRA_RUNTIME_STATE_ROOT=str(DATA/'runtime'),CONTEXTRA_MODEL_ROOT=str(DATA/'models'),FASTAPI_HOST_PORT='35000',
        CONTEXTRA_SECURE_ANALYTICS_IMAGE=images['analytics'],CONTEXTRA_SIDECAR_IMAGE=images['ai-control-sidecar'],
        CONTEXTRA_SIDECAR_BASE_IMAGE=images['ai-control-sidecar'],CONTEXTRA_GATEWAY_IMAGE=images['ai-gateway'],
        AI_BRIDGE_SECRET_ROOT=str(SITE/'bridge'),AI_BRIDGE_SESSION_ROOT=str(SITE/'bridge-session'),AI_BRIDGE_TLS_ROOT=str(SITE/'tls'),
        AI_CONTROL_SERVER_ID='AI-01',AI_CONTROL_MANAGER_BASE_URL='https://'+WEB,
        AI_CONTROL_EVENT_ENDPOINT='https://'+WEB+'/api/v1/events',AI_CONTROL_HOST_PORT='38443',
        AI_ARTIFACT_ACCESS_POLICY='lan_public',AI_ARTIFACT_LAN_CIDR='192.168.30.0/24',
        CONTEXTRA_ARTIFACT_PUBLIC_BASE='https://'+AI+':38443/artifacts',CONTEXTRA_EVENT_ARTIFACT_ENABLED='1',
        CONTEXTRA_WEB_ARTIFACT_ENABLED='1',CONTEXTRA_CONTROL_TEMPLATE_SOURCE=str(SITE/'camera-template.json'))
    put(SITE/'runtime.env','\n'.join(k+'='+v for k,v in env.items())+'\n')
    common=json.loads((STAGE/'runtime-common.json').read_text())
    common.update(REDIS_URL='redis://contextra_internal:'+passwords['internal']+'@redis:6379/0',
        CONTEXTRA_METADATA_REDIS_URL='redis://contextra_publisher:'+passwords['publisher']+'@redis:6379/0',
        CONTEXTRA_ARTIFACT_CAP_BYTES='400000000000',CONTEXTRA_ARTIFACT_MIN_FREE_BYTES='100000000000',
        CONTEXTRA_ARTIFACT_RESUME_FREE_BYTES='100000000000',CONTEXTRA_ARTIFACT_RETENTION_ENABLED='true',
        CONTEXTRA_ARTIFACT_EXTERNAL_RESERVE_BYTES=str(4*96*1024**2),
        CONTEXTRA_TRAINING_EXTERNAL_RESERVE_BYTES=str(64*128*1024**2))
    volumes=[bind(DATA/'artifacts','/data/contextra/artifacts'),bind(DATA/'training','/data/contextra/training')]
    for name in ('RFDETRKeypointPreview','RFDETRFireSmoke','Awiros_person_and_head_detection'):
        volumes.append(bind(DATA/'models/triton'/name,'/opt/contextra/models/triton/'+name,True))
    overlay={'services':{
        'analytics':dict(environment=common,volumes=volumes,shm_size='2gb',cpus=24,mem_limit='40g',pids_limit=4096,stop_grace_period='100s'),
        'postgresql':dict(image=images['postgresql'],cpus=2,mem_limit='2g'),
        'redis':dict(image=images['redis'],cpus=2,mem_limit='3g',
            command=['redis-server','/usr/local/etc/redis/redis.conf','--maxmemory','2gb','--maxmemory-policy','allkeys-lru'],
            ports=[dict(host_ip=AI,target=6379,published='16379',protocol='tcp')],
            volumes=[bind(SITE/'redis/redis.conf','/usr/local/etc/redis/redis.conf',True),bind(SITE/'redis/users.acl','/usr/local/etc/redis/users.acl',True)],
            environment={'REDISCLI_AUTH':passwords['health']},
            healthcheck=dict(test=['CMD-SHELL','redis-cli --user contextra_health ping'],interval='10s',timeout='5s',retries=5)),
        'ai-gateway':dict(stop_signal='SIGTERM')
    }}
    dump(SITE/'site.compose.json',overlay)
    for folder in (SITE/'bridge',SITE/'tls',SITE/'bridge-session'):
        os.chown(folder,10001,10001)
        for f in folder.iterdir():os.chown(f,10001,10001)
    sys.path.insert(0,str(SOURCE/'tools'))
    from secure_bridge_tls import prepare as prepare_tls
    prepare_tls(SITE/'tls',AI)
    for f in (SITE/'tls').iterdir():os.chown(f,10001,10001)
    # Pinned redis:7-alpine UID/GID, verified again before creating services.
    os.chown(SITE/'redis/users.acl',999,1000)
    dump(STAGE/'runtime-prepared.json',dict(status='INPUTS_ONLY',source=str(SOURCE),site=str(SITE),
        project=PROJECT,web_login_requests=0,services_started=False,storage_uuid=UUID))
    print('RUNTIME_INPUTS_PREPARED_NO_LOGIN_NO_START')

if __name__=='__main__':main()
