import copy,json,importlib.util
from pathlib import Path
from unittest.mock import patch
P=Path(__file__).resolve().parent
spec=importlib.util.spec_from_file_location('survey_verify',P/'verify.py');v=importlib.util.module_from_spec(spec);spec.loader.exec_module(v)
original=v.load
def raw_change(doc,fn):
    body=json.loads(doc['raw']);fn(body);doc['raw']=json.dumps(body,ensure_ascii=False,separators=(',',':'))
mutations=[
('C full Food camel output missing','private/C/private/wire-FOOD_DETAIL2.json',lambda d:raw_change(d,lambda b:b['data']['detail'].__setitem__('food_Intolerance',''))),
('Problem score type corruption','private/wire-PROBLEM_DETAIL2.json',lambda d:raw_change(d,lambda b:b['data']['detail']['score'].__setitem__('protein','2'))),
('Meals tree order corruption','private/wire-MEALS_DETAIL2.json',lambda d:raw_change(d,lambda b:b['data']['detail']['meals'].reverse())),
('Retained Food answer changed','private/wire-FOOD_UPDATE.json',lambda d:next(r for r in d['after']['nutrition_lack'] if r['type']==11 and r['reference_id']==3).__setitem__('checkout_status',0)),
('Failed rollback effect concealed','private/wire-PROBLEM_UPDATE.json',lambda d:d['after']['nutrition_meals'][0].__setitem__('other_text','corrupt')),
('Actual included source drift','private/wire-FOOD_DETAIL2.json',lambda d:d['included_source_sha256'].__setitem__(next(iter(d['included_source_sha256'])),'0'*64)),
('Client wire byte drift','private/client-FOOD_DETAIL2.json',lambda d:d.__setitem__('raw',d['raw']+' ')),
('Token cleanup absent','private/cleanup.json',lambda d:d.__setitem__('token_files_erased',False)),
('Extra retry body not frozen','private/cases-extra.json',lambda d:d['PROBLEM_UPDATE_TOOL_RETRY'].__setitem__('body_raw','{}')),
('Native master generated ID incorrect','private/C/private/wire-FOOD_FRESH_CREATE.json',lambda d:d.__setitem__('master_generated_native_ID',999)),
('Original protected dictionary mutated','private/wire-FOOD_DETAIL2.json',lambda d:d['protected_after']['dictionary'][0].__setitem__('enum_name','changed')),
]
result=[]
for name,relative,mutate in mutations:
    target=P/relative
    def bad_load(path):
        doc=copy.deepcopy(original(path))
        if path==target:mutate(doc)
        return doc
    v.COUNT=0
    try:
        with patch.object(v,'load',bad_load):v.run()
    except (AssertionError,KeyError,ValueError,TypeError) as error:result.append({'case':name,'rejected':True,'reason':str(error)[:240]})
    else:raise AssertionError('Oracle accepted '+name)
v.COUNT=0;green=v.run();report={'negative_cases':result,'all_rejected':True,'final_green_assertions':green['assertions'],'HTTP':0,'DML':0,'DDL':0}
(P/'negative-verifier.json').write_text(json.dumps(report,ensure_ascii=False,indent=2)+'\n')
print(json.dumps({'negative_cases':len(result),'all_rejected':True,'final_green_assertions':green['assertions'],'HTTP':0,'DML':0,'DDL':0}))
