#!/usr/bin/env python3
"""Evidence-only mutations: wire/URL/time/root/version/cleanup cannot be ignored."""
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-local-copy')
b,c=map(Path,sys.argv[1:]);original=json.loads((c/'responses.json').read_text());report=json.loads((c/'report.json').read_text())
script=Path(__file__).with_name('compare.py');passed=[]
def shape(v):
    if isinstance(v,dict):return {'type':'object','properties':{k:shape(x) for k,x in sorted(v.items())} if v else []}
    if isinstance(v,list):return {'type':'array','items':[shape(x) for x in v]}
    if v is None:return {'type':'NULL'}
    if isinstance(v,bool):return {'type':'boolean'}
    if isinstance(v,(int,float)):return {'type':'number'}
    return {'type':'string'}
with tempfile.TemporaryDirectory(prefix='cdx-file-http-compare-') as tmp:
    target=Path(tmp)/'C';target.mkdir()
    for name in ['fixture_map.json','source-scenarios.json']:shutil.copyfile(c/name,target/name)
    def run(name,mutate=None,mutate_report=None,accept=False):
        data=deepcopy(original);r=deepcopy(report)
        if mutate:mutate(data)
        if mutate_report:mutate_report(r)
        for response in data.values():response['wire_shape']=shape(response['body'])
        (target/'responses.json').write_text(json.dumps(data,ensure_ascii=False));(target/'report.json').write_text(json.dumps(r))
        process=subprocess.run([sys.executable,str(script),str(b),str(target)],capture_output=True,text=True)
        if (process.returncode==0)!=accept:raise AssertionError('Comparator did not enforce '+name)
        passed.append(name)
    def file(d):return d['S_FILES_LIST']['body']['data']['list']['data'][0]
    run('36 original HTTP/source/wire cases',accept=True)
    run('URL value changed',lambda d:file(d).__setitem__('external_url',file(d)['external_url']+'/CHANGED'))
    run('ID number stringified',lambda d:file(d).__setitem__('file_id',str(file(d)['file_id'])))
    run('timestamp not independently true',lambda d:file(d).__setitem__('create_time','2000-01-01 00:00:00'))
    run('file array order changed',lambda d:d['S_FILES_LIST']['body']['data']['list']['data'].reverse())
    run('empty wire data array changed to object',lambda d:d['S_FILES_CLEANED']['body']['data']['list'].__setitem__('data',{}))
    run('unsafe deletion target exists',mutate_report=lambda r:r['list_environment_guards'][0]['deletion_targets_exist'].__setitem__('vendor/topthink/framework/src/think/Filesystem.php',True))
    run('actual root is old root',mutate_report=lambda r:r['list_environment_guards'][0].__setitem__('actual_new_root',False))
    run('version branch is not 0.0.1',mutate_report=lambda r:r['list_environment_guards'][0].__setitem__('actual_version','2.0.7'))
    run('owned data left behind',mutate_report=lambda r:r['independent_remaining'].__setitem__('upload_file',1))
    run('StorageDriver invoked',mutate_report=lambda r:r.__setitem__('storage_guard_attempts',1))
    run('expected cycle rejection falsely succeeds',lambda d:d['S_GROUP_CYCLE_REJECT']['body'].__setitem__('status',200))
    run('missing interface case',lambda d:d.pop('S_FILES_EDIT'))
print(json.dumps({'tests':len(passed),'passed':passed,'private_temporary_copies_cleaned':True},indent=2))
