#!/usr/bin/env python3
"""Mutation tests on private runtime copies; no payload is written to the repository."""
from copy import deepcopy
import json
from pathlib import Path
import shutil
import subprocess
import sys
import tempfile

if len(sys.argv)!=3:
    raise SystemExit('Expected B-runtime C-runtime')
b,c=map(Path,sys.argv[1:])
original=json.loads((c/'responses.json').read_text())
long_case='STORE_BYTES_49152_LIST'
mapping=json.loads((c/'fixture_map.json').read_text())
owned_id=int(mapping['source_rows'][long_case]['help_id'])
own_index=next(i for i,r in enumerate(original[long_case]['body']['data']['list']['data']) if r['help_id']==owned_id)
script=Path(__file__).with_name('compare.py')
passed=[]
with tempfile.TemporaryDirectory(prefix='cdx-help-comparator-') as tmp:
    copy=Path(tmp)/'C'
    shutil.copytree(c,copy)
    def run(name,mutate=None,accept=False):
        data=deepcopy(original)
        if mutate: mutate(data)
        (copy/'responses.json').write_text(json.dumps(data,ensure_ascii=False))
        result=subprocess.run([sys.executable,str(script),str(b),str(copy)],capture_output=True,text=True)
        if (result.returncode==0)!=accept:
            raise AssertionError('Comparator did not enforce '+name)
        passed.append(name)
    def row(data): return data[long_case]['body']['data']['list']['data'][own_index]
    run('baseline 84 exact scenarios',accept=True)
    run('TEXT truncation',lambda d: row(d).__setitem__('content',row(d)['content'][:-1]))
    run('TEXT string-to-number',lambda d: row(d).__setitem__('content',123))
    run('identifier number-to-string',lambda d: row(d).__setitem__('help_id',str(owned_id)))
    run('timestamp not equal independent source',lambda d: row(d).__setitem__('create_time','2000-01-01 00:00:00'))
    run('business failure',lambda d: d['STORE_EMPTY_ADD']['body'].__setitem__('status',500))
    run('missing scenario',lambda d: d.pop('STORE_EMPTY_ADD'))
    run('uncontracted response key',lambda d: d['STORE_EMPTY_ADD']['body'].__setitem__('unexpected',True))
    run('same dynamic trace',lambda d: d['STORE_EMPTY_ADD']['body'].__setitem__('trace_id',
        json.loads((b/'responses.json').read_text())['STORE_EMPTY_ADD']['body']['trace_id']))
    array_case=next((key for key,value in original.items()
        if isinstance(value['body'].get('data'),dict)
        and len(value['body']['data'].get('list',{}).get('data',[]))>1),None)
    if array_case is not None:
        run('array reordering',lambda d: d[array_case]['body']['data']['list']['data'].reverse())
    else:
        # Still prove added rows are not tolerated when every natural page has one row.
        run('array extra item',lambda d: d[long_case]['body']['data']['list']['data'].append(deepcopy(row(d))))
print(json.dumps({'tests':len(passed),'passed':passed,'private_temporary_copies_cleaned':True},indent=2))
