#!/usr/bin/env python3
"""Supplementary exact own effects and complete response, without DB or HTTP."""
import copy
import json
from pathlib import Path

ROOT=Path(__file__).parent/'api-private-evidence'
MARKER='CDXMATSC261011'
NUMERIC={'id','pid','level','status','leaf_flag','type','is_delete'}
MESSAGES={'A1':'添加成功','A2':'添加成功','A3':'添加成功','A4':'修改成功','A5':'','A6':'删除成功'}

def equal(a,b):
    assert type(a) is type(b),(type(a),type(b))
    if isinstance(a,dict):
        assert a.keys()==b.keys()
        for k in a:equal(a[k],b[k])
    elif isinstance(a,list):
        assert len(a)==len(b)
        for x,y in zip(a,b):equal(x,y)
    else:assert a==b,(a,b)

def verify_wire(wire,lane,step,roles):
    before=wire['source_before']['material_category'];after=wire['source_after']['material_category']
    old={str(r['id']):r for r in before};new={str(r['id']):r for r in after}
    integer=lambda value:str(value) if lane=='B' else int(value)
    data=[]
    if step in ['A1','A2','A3']:
        role={'A1':'P1','A2':'P2','A3':'L'}[step];pk=roles[role];assert pk not in old and pk in new
        row=new[pk]
        expected={'id':integer(pk),'pid':integer(roles['P1'] if role=='L' else 0),
            'name':MARKER+'-'+role,'category_path':roles['P1'] if role=='L' else '',
            'level':integer(2 if role=='L' else 1),'status':integer(1),'leaf_flag':integer(1),
            'type':integer(1),'is_delete':integer(0),'update_time':row['update_time'],
            'create_time':row['create_time'],'create_by':'admin'}
        equal(row,expected)
        expected_old=copy.deepcopy(old)
        if role=='L':
            expected_old[roles['P1']]['leaf_flag']=integer(0)
            expected_old[roles['P1']]['update_time']=new[roles['P1']]['update_time']
        equal({k:v for k,v in new.items() if k!=pk},expected_old)
    elif step in ['A4','A6']:
        expected=copy.deepcopy(old)
        for role,pk in roles.items():
            expected[pk]['update_time']=new[pk]['update_time']
            if step=='A6':expected[pk]['is_delete']=integer(1)
        if step=='A4':
            expected[roles['P1']]['leaf_flag']=integer(1)
            expected[roles['P2']]['leaf_flag']=integer(0)
            expected[roles['L']].update(pid=integer(roles['P2']),category_path=roles['P2'],name=MARKER+'-L-U',level=integer(2))
        equal(new,expected)
    else:
        assert step=='A5';equal(after,before)
        row=new[roles['L']];data={k:int(v) if k in NUMERIC else v for k,v in row.items()}
        data['pname']=new[roles['P2']]['name']
    body=json.loads(wire['body'])
    equal(body,{'code':0,'message':MESSAGES[step],'data':data})
    if step=='A5':
        body=copy.deepcopy(body);body['data'].update(id='own.L',pid='own.P2',category_path='own.P2',
            create_time='validated-own-create-clock',update_time='validated-own-update-clock')
    return body

def verify():
    bodies={};count=0
    for lane in ['B','C']:
        p=ROOT/lane;load=lambda n:json.loads((p/n).read_text())
        roles={row['name'].split(MARKER+'-')[1]:str(row['id']) for row in load('final.json')['lease']}
        for step in ['A'+str(i) for i in range(1,7)]:
            bodies[(lane,step)]=verify_wire(load(step+'.wire.json'),lane,step,roles);count+=1
        for step,status in [('D7',0),('D8',1)]:
            r=load(step+'.result.json');expected=copy.deepcopy(r['source_before'])
            row=next(row for row in expected['material_category'] if str(row['id'])==roles['P2'])
            row['status']=str(status) if lane=='B' else status;row['update_time']='2002-02-02 02:02:02'
            equal(r['source_after'],expected)
    for step in ['A'+str(i) for i in range(1,7)]:equal(bodies[('B',step)],bodies[('C',step)])
    return dict(HTTP=0,DB=0,full_response_and_own_effect_checks=count,complete_BC_body_pairs=6,
                explicit_time_all_other_fields_preserved_checks=4)

if __name__=='__main__':print(json.dumps(verify()))
