import csv
import hashlib
import io
import json
import os
import pathlib
import re
import subprocess
import tarfile

os.umask(0o077)
R = pathlib.Path(__file__).parent
NAME = 'contextra-analytics-1'
LIB = '/opt/nvidia/deepstream/deepstream/lib/libnvds_service_maker.so'
def command(args):
    return subprocess.check_output(args, text=True, timeout=20)
disassembly = command(['docker','exec',NAME,'objdump','-d','-C',
    '--disassemble=deepstream::DataReceiver::consume(deepstream::Buffer)',LIB])
constant = command(['docker','exec',NAME,'objdump','-s','--start-address=0x895a0','--stop-address=0x895b0',LIB])
assert 'nanosleep@plt' in disassembly and '01000000 00000000 00000000 00000000' in constant
(R/'receiver-disassembly.txt').write_text(disassembly + '\n' + constant)
libhash = command(['docker','exec',NAME,'sha256sum',LIB]).split()[0]
data = subprocess.check_output(['docker','cp',NAME+':/tmp/contextra_cfg/.','-'],timeout=20)
config_hashes = []
canonical = pathlib.Path('/tmp/codex/ltb1021/2026-09-10_preprocess-isolation_r01/generated')
reference = {p.suffix: p.read_text() for p in canonical.iterdir() if p.is_file()}
def normalize(text):
    # These are generated ID substitutions, not edits to the configuration.
    return re.sub(r'(unique_id\s*:\s*|unique-id\s*=\s*|target-unique-ids\s*=\s*)\d+', r'\1ID', text)
with tarfile.open(fileobj=io.BytesIO(data)) as archive:
    for member in archive:
        if member.isfile() and 'medium_' in member.name:
            body = archive.extractfile(member).read()
            suffix = pathlib.Path(member.name).suffix
            config_hashes.append({'kind':suffix,'sha256':hashlib.sha256(body).hexdigest(),
                'equal_after_component_id_normalization': normalize(body.decode()) == normalize(reference[suffix])})
assert config_hashes and all(c['equal_after_component_id_normalization'] for c in config_hashes)
before = json.loads((R/'stats-before.json').read_text())['model_stats'][0]['inference_stats']
after = json.loads((R/'stats-after.json').read_text())['model_stats'][0]['inference_stats']
stats = {}
for k in ['success','queue','compute_input','compute_infer','compute_output']:
    n = int(after[k]['count'])-int(before[k]['count'])
    ns = int(after[k]['ns'])-int(before[k]['ns'])
    stats[k] = {'count':n,'mean_ms':ns/n/1e6 if n else None}
probe = json.loads((R/'probe.json').read_text())
resources = json.loads((R/'resources.json').read_text())
cpu = [float(x['cpu_mem'].split('|')[0].rstrip('%')) for x in resources['resource_samples'] if x['cpu_mem']]
summary = {'baseline':probe,'triton_full_probe_interval':stats,'resources':resources,
           'cpu_peak_percent_including_model_load':max(cpu),
           'installed_sdk_library_sha256':libhash,'generated_config_comparison':config_hashes,
           'audit':{'production_success_return':0,'sdk_expected_consumed_buffer_count':1,
                    'zero_return_sleep_seconds':1,'proof':'public header + exact installed ELF consume symbol and timespec',
                    'production_fix_applied':False,'production_speed_after_fix':'UNVERIFIED'},
           'rtp_contrast':{'runs':0,'reason':'Concrete consumer return-contract defect identified; synthetic input cannot form matched RTSP contrast.'},
           'limitations':['No RTSP/decoder test','No production callback or Frame identity path',
                          'No direct queue-level or source-pad measurement','No raw RTP or Web synchronization acceptance',
                          'Consumer return value differs from production; not an isolated RTP comparison',
                          'Triton stats include warmup and cleanup, unlike FPS measurement']}
(R/'summary.json').write_text(json.dumps(summary,indent=2))
with (R/'summary.csv').open('w') as f:
    w = csv.writer(f)
    w.writerow(['scope','metric','value','unit'])
    for k,v in probe['fps'].items():
        w.writerow(['measurement',k,v,'frames/s'])
    for k,v in probe['latency_ms'].items():
        w.writerow(['measurement',k,v['mean'],'ms'])
    for k,v in stats.items():
        w.writerow(['whole_probe_triton',k,v['mean_ms'],'ms'])
    w.writerow(['sdk_static','consume_zero_sleep',1,'s'])
print(json.dumps({'generated_config_equal':True,'configs':len(config_hashes),'triton':stats,
                  'cpu_peak_percent':max(cpu),'library_sha256':libhash},indent=2))
