import contextlib,ctypes,json,os,subprocess,time,unittest
from pathlib import Path
import numpy as np
os.umask(0o077)
R=Path('/evidence');P=Path('/prior');label=os.environ.get('VERIFY_LABEL','source')
root=os.environ.get('TEST_ROOT','/source')
summary={}
with (R/(label+'.log')).open('x') as log,contextlib.redirect_stdout(log),contextlib.redirect_stderr(log):
    os.environ['DATABASE_URL']='postgresql://fixture:fixture@127.0.0.1:1/fixture'
    os.environ['REDIS_URL']='redis://127.0.0.1:1/0'
    suite=unittest.TestSuite()
    for pattern in ('test_pose_nms.py','test_pose_path.py','test_intrusion.py','test_intrusion_connection.py','test_output_settings.py','test_capture_boundary.py'):
        suite.addTests(unittest.defaultTestLoader.discover(root+'/tests',pattern=pattern))
    result=unittest.TextTestRunner(stream=log,verbosity=2).run(suite)
    summary.update(tests=result.testsRun,errors=len(result.errors),failures=len(result.failures))
    from app.pose_nms import pose_nms_indices
    from app.contracts.frames import DetectionObservation,FrameEnvelope
    lib=ctypes.CDLL(str(P/'pose_decode.so'))
    ptr=np.ctypeslib.ndpointer(dtype=np.float32,flags='C_CONTIGUOUS')
    lib.decode_pose.argtypes=[ptr,ptr,ptr,ptr];lib.decode_pose.restype=ctypes.c_int
    rows=[]
    for sec in (20,23,26):
        arrays=[np.fromfile(P/f'compare-{sec}'/(name+'.bin'),np.float32).reshape(shape) for name,shape in
                (('dets',(1,100,4)),('labels',(1,100,2)),('keypoints',(1,100,34,8)))]
        output=np.empty((100,56),np.float32);n=lib.decode_pose(*arrays,output)
        assert n>=0
        f=FrameEnvelope('fixture','fixture','fixture','fixture',1,sec*10,sec*10**9,0,1280,720)
        obs=tuple(DetectionObservation(f,'RFDETRKeypointPreview',0,float(r[0]),tuple(map(float,r[1:5]))) for r in output[:n])
        for _ in range(10):pose_nms_indices(obs)
        timings=[]
        for _ in range(100):
            start=time.perf_counter_ns();keep=pose_nms_indices(obs);timings.append((time.perf_counter_ns()-start)/1e6)
        rows.append(dict(pts_s=sec,input=n,kept=len(keep),suppressed=n-len(keep),shown_before=sum(o.score>=.25 for o in obs),
                         shown_after=sum(obs[i].score>=.25 for i in keep),mean_ms=float(np.mean(timings)),p95_ms=float(np.percentile(timings,95)),
                         kept_indices=list(keep)))
    summary['nms']=rows
    p=subprocess.run(['python3',root+'/tests/sdk_pose_probe.py','/prior/pose_fixture.so'],stdout=log,stderr=log,timeout=45)
    summary['sdk']=p.returncode
(R/(label+'-verify.json')).write_text(json.dumps(summary,indent=2));print(json.dumps(summary))
raise SystemExit(bool(summary['errors'] or summary['failures'] or summary['sdk']))
