#!/usr/bin/env python3
"""Root supplementary full-body / full own-row oracle; no DB, HTTP or writes."""
import copy
from datetime import datetime
import json
from pathlib import Path
import re

ROOT = Path(__file__).parent/'private-evidence'
NUMERIC = {'id', 'status', 'is_del', 'order_no', 'type', 'number'}
FIELDS = NUMERIC | {'uuid', 'name', 'demo', 'create_time', 'create_by'}
MESSAGES = {1:'新建成功', 2:'编辑成功', 3:'更改状态成功', 4:'状态修改失败', 5:'删除分类成功'}

def equal(a, b):
    assert type(a) is type(b), (type(a), type(b))
    if isinstance(a, dict):
        assert a.keys() == b.keys()
        for key in a: equal(a[key], b[key])
    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 body(wire):
    value = json.loads(wire['body'])
    if 'trace_id' in value:
        assert re.fullmatch('[0-9a-f]{13}', value.pop('trace_id'))
    return value

def verify_case(wire, lane, step, historical=False):
    params = wire['params']
    before = wire['source_before']['nutrition_category']
    after = wire['source_after']['nutrition_category']
    if step == 1:
        added = [row for row in after if row not in before]
        assert len(added) == 1 and len(after) == len(before)+1
        row = added[0]
        assert set(row) == FIELDS
        assert re.fullmatch('[0-9A-F]{8}(?:-[0-9A-F]{4}){3}-[0-9A-F]{12}', row['uuid'])
        assert row['create_by'] == 'admin'
        stamp = row['create_time']
        if lane == 'C': assert stamp.endswith('.000000'); stamp = stamp[:-7]
        assert re.fullmatch(r'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}', stamp)
        delta = (datetime.fromisoformat(wire['clock_after'])-datetime.fromisoformat(stamp)).total_seconds()
        assert -1 <= delta <= wire['duration_seconds']+2
        for key, value in params.items(): assert str(row[key]) == value, key
        for key in NUMERIC: assert type(row[key]) is (str if lane == 'B' else int), key
        equal([r for r in after if r['uuid'] != row['uuid']], before)
    else:
        uuid = params['uuid']
        old = next(row for row in before if row['uuid'] == uuid)
        if step == 5:
            assert not any(row['uuid'] == uuid for row in after)
            equal(after, [row for row in before if row['uuid'] != uuid])
        else:
            new = next(row for row in after if row['uuid'] == uuid)
            expected = copy.deepcopy(old)
            for key, value in params.items():
                if key != 'uuid': expected[key] = int(value) if lane == 'C' and key in NUMERIC else value
            equal(new, expected)
            equal([r for r in after if r['uuid'] != uuid], [r for r in before if r['uuid'] != uuid])
            if step == 4: equal(before, after)
    old_red = historical and lane == 'C' and step == 4
    expected = {'code':0 if step != 4 or old_red else 1,
                'message':MESSAGES[3 if old_red else step], 'data':[]}
    equal(body(wire), expected)

def verify():
    wires = {}
    for phase, prefix, steps in [('original','N',range(1,6)), ('noop','R',(1,3,4,5))]:
        for lane in ['B','C']:
            for side in ['P','M']:
                for step in steps:
                    directory = lane if phase == 'original' else lane+'-noop'
                    wire = json.loads((ROOT/directory/f'{prefix}-{side}{step}.wire.json').read_text())
                    assert wire['status'] == 200
                    verify_case(wire, lane, step, phase == 'original')
                    wires[(phase,lane,side,step)] = wire
    pairs = 0
    for side in ['P','M']:
        for phase, steps in [('original',(1,2,3,5)),('noop',(1,3,4,5))]:
            for step in steps:
                equal(body(wires[(phase,'B',side,step)]), body(wires[(phase,'C',side,step)]))
                pairs += 1
        for lane in ['B','C']:
            for step in [1,3,5]:
                equal(body(wires[('original',lane,side,step)]), body(wires[('noop',lane,side,step)]))
    return dict(HTTP_nutrition=36, complete_BC_body_pairs=pairs,
                own_full_row_and_effect_checks=len(wires), original_C_noop_reds=2,
                repeated_noop_complete_source_unchanged=True, DB=0, HTTP_replayed=0)

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