#!/usr/bin/env python3
"""Reproduce synthetic measurement-completeness cases. Python3,standard library only."""
import argparse,csv,json,math
from pathlib import Path

def evaluate(eligible,good,bad,unknown):
    values=(eligible,good,bad,unknown)
    if any(type(v) is not int or v<0 for v in values):
        raise ValueError('Counts must be nonnegative integers.')
    if good+bad+unknown!=eligible:
        raise ValueError('Good,bad and unknown must partition the eligible cohort.')
    observed=good+bad
    return {'eligible':eligible,'good':good,'bad':bad,'unknown':unknown,
            'state':'no eligible events' if not eligible else 'no observed outcomes' if not observed else 'incomplete' if unknown else 'complete',
            'confirmed_good_fraction':good/eligible if eligible else None,
            'possible_good_fraction_upper':(good+unknown)/eligible if eligible else None,
            'observed_only_good_fraction':good/observed if observed else None,
            'observed_fraction':observed/eligible if eligible else None}

def self_test():
    a=evaluate(1000,960,30,10)
    assert math.isclose(a['confirmed_good_fraction'],.96)
    assert math.isclose(a['possible_good_fraction_upper'],.97)
    assert a['observed_only_good_fraction']!=a['confirmed_good_fraction']
    assert evaluate(0,0,0,0)['confirmed_good_fraction'] is None
    assert evaluate(100,0,0,100)['state']=='no observed outcomes'
    assert evaluate(100,0,100,0)['possible_good_fraction_upper']==0
    assert evaluate(100,50,0,50)['confirmed_good_fraction']==.5
    for counts in [(10,10,1,0),(-1,0,0,0),(True,1,0,0)]:
        try:evaluate(*counts)
        except ValueError:pass
        else:raise AssertionError('Invalid cohort accepted')
    print('Passed:complete,partial,zero-traffic,missing,all-bad and invalid-cohort cases.')

if __name__=='__main__':
    parser=argparse.ArgumentParser(description=__doc__)
    parser.add_argument('csv_file',nargs='?')
    parser.add_argument('--self-test',action='store_true')
    args=parser.parse_args()
    if args.self_test:self_test()
    elif args.csv_file:
        with Path(args.csv_file).open(newline='') as f:
            for row in csv.DictReader(f):
                result=evaluate(*(int(row[k]) for k in ('eligible','good','bad','unknown')))
                print(json.dumps({'case':row['case'],**result}))
    else:parser.error('Provide the synthetic CSV file or --self-test.')
