"""Full MaleCNS matched auditory-interface assay, one identified trade at a time.

Does not sign, trade, or modify the continuous laboratory checkpoint. Each assay
starts from the same resting reference state; the two seed identities are kept.
The externally frozen rule is an engineering rule, not a Cell mating threshold.
"""
from pathlib import Path
import argparse, datetime, json
import numpy as np
from continuous import Model, ROOT, sha
from brian_reference import ReferenceState

def assay(kind):
    cfg=json.loads((ROOT/'lib/reproduction-config.json').read_text(encoding='utf-8'))
    if kind not in cfg['inputs']: raise ValueError('Unsupported trade direction')
    model=Model(); inputs=np.flatnonzero(model.fb.types==cfg['inputs'][kind])
    readout=np.flatnonzero(model.fb.types==cfg['readout'])
    if not len(inputs) or not len(readout): raise ValueError('Exact MaleCNS populations missing')
    report=dict(schema='fruit.market-assay.v1',ruleVersion=cfg['version'],kind=kind,
      asOf=datetime.datetime.now(datetime.timezone.utc).isoformat(),
      graphSha256=model.manifest['graphSha256'],modelSha256=sha(ROOT/'science/brian_reference.py'),
      runnerSha256=sha(__file__),ruleSha256=sha(ROOT/'lib/reproduction-config.json'),neurons=model.fb.n,
      inputType=cfg['inputs'][kind],inputBodyIds=model.fb.bodies[inputs].tolist(),
      readoutType=cfg['readout'],readoutBodyIds=model.fb.bodies[readout].tolist(),
      inputHz=cfg['inputHz'],windowMs=cfg['windowMs'],trials=[],
      stateScope='Independent resting-state assays; not a continuation of the laboratory worker',
      learningEnabled=False,biologicalMatingEstablished=False)
    for parent in cfg['parents']:
      for condition in ['connected','no-input','blocked']:
        state=ReferenceState(model.fb,inputs,mute=inputs if condition=='blocked' else ())
        rng=np.random.default_rng(parent['seed']);frames=[]
        for window in range(cfg['windows']):
          counts=np.zeros(model.fb.n,np.int32);event_count=0
          for _ in range(100):
            draws=rng.random(len(inputs))
            hits=inputs[draws<cfg['inputHz']*.0002] if condition!='no-input' and cfg['stimulusWindows'][0]<=window<=cfg['stimulusWindows'][1] else np.array([],np.int64)
            event_count+=len(hits);counts[state.step(hits)]+=1
          if not np.isfinite(state.v).all(): raise ValueError('Nonfinite neural result')
          frames.append(dict(window=window+1,modelMs=(window+1)*20,inputEvents=event_count,
            activeNeurons=int(np.count_nonzero(counts)),totalSpikes=int(counts.sum()),
            readoutHz=float(counts[readout].mean()/.020),readoutSpikes=int(counts[readout].sum())))
        report['trials'].append(dict(specimenId=parent['id'],seed=parent['seed'],condition=condition,frames=frames))
    return report

if __name__=='__main__':
    p=argparse.ArgumentParser(description=__doc__);p.add_argument('--kind',choices=['buy','sell'],required=True);p.add_argument('--out',type=Path,required=True)
    args=p.parse_args(); result=assay(args.kind);args.out.parent.mkdir(parents=True,exist_ok=True)
    args.out.write_text(json.dumps(result,allow_nan=False,separators=(',',':')),encoding='utf-8')
    print(json.dumps({'kind':args.kind,'trials':len(result['trials']),'peaks':[max(f['readoutHz'] for f in t['frames']) for t in result['trials']]}))
