#!/usr/bin/env python3
import json
from pathlib import Path


def exact(a, b, path='$'):
    if type(a) is not type(b): raise AssertionError(f'type mismatch {path}')
    if isinstance(a, dict):
        if set(a) != set(b): raise AssertionError(f'keys mismatch {path}')
        for key in a: exact(a[key], b[key], f'{path}.{key}')
    elif isinstance(a, list):
        if len(a) != len(b): raise AssertionError(f'length mismatch {path}')
        for i, values in enumerate(zip(a, b)): exact(*values, f'{path}[{i}]')
    elif a != b: raise AssertionError(f'value mismatch {path}')


def validate(lane):
    assert lane['error'] is None and lane['metadata_gate_verified'] is True
    assert len(lane['cases']) == 46 and len(lane['original_proofs']) == 20
    assert lane['loaded_boundary']['plan_serializer_sha'] == 'd61d53d6c13d516698eacbad14d21f3032f5ac7e206a31f03412e3348e4f3a5a'
    assert len({(c['method'], c['path']) for c in lane['cases']}) == 18
    assert sum(c['body']['status'] == 500 for c in lane['cases']) == 4
    for case in lane['cases']:
        assert case['http_status'] == 200 and case['trace_format_valid'] is True
        assert case['body']['status'] in (200, 500)
    for proof in lane['original_proofs']:
        assert proof['all_requested_fields_and_json_values_verified'] is True
        assert proof['owned_primary_key_and_store_verified'] is True
    assert len(lane['write_audit']) == 20
    for event in lane['write_audit']:
        assert event['owned_scope_verified'] is True
        assert event['table'] in ('yoshop_user_grade', 'yoshop_recharge_plan')
    clean = lane['cleanup']
    assert not any(clean['fresh_pdo_owned_rows'].values())
    assert clean['tokens_absent'] is True and clean['natural_two_tables_full_sha_unchanged'] is True
    assert clean['owned_references_zero'] is True and len(clean['owned_reference_columns']) == 7
    assert all(c['remaining_owned_references'] == 0 for c in clean['owned_reference_columns'])
    assert all(c['own_pk_store_exact_name'] is True for c in clean['delete_scopes'])
    for column in clean['nonreference_homonym_columns']:
        assert column['table'] == 'yoshop_ai_training_plan' and column['column'] == 'plan_id'
        assert column['column_key'] == 'PRI' and column['column_comment'] == '训练计划ID'
        assert column['table_comment'] == 'AI跑步训练计划表' and column['foreign_key'] is False


def compare(b, c, baseline):
    validate(b); validate(c)
    for key in ('cases', 'original_proofs', 'write_audit'):
        exact(b[key], c[key], key)
    exact(b['loaded_boundary'], c['loaded_boundary'], 'loaded_boundary')
    # Input/runtime times and synthetic IDs were independently verified BEFORE
    # per-row event mapping. No monetary wire/type or business value is ignored.
    exact(baseline['cases'], b['cases'], 'mysql_before_after_complete_wire')
    exact(baseline['original_proofs'], b['original_proofs'], 'mysql_before_after_original_values')
    return {'actual_methods': sorted({f"{c['method']} {c['path']}" for c in b['cases']}),
            'http_pairs': 46, 'successful_status_pairs': 42, 'successful_write_pairs': 20,
            'nonempty_read_pairs': 14, 'empty_sequence_boundary_pairs': 8,
            'expected_duplicate_weight_refusals': 4,
            'independent_original_pairs': 20, 'complete_wire_type_value_order_differences': 0,
            'mysql_before_after_complete_wire_differences': 0,
            'monetary_wire_numeric_normalization': False}


if __name__ == '__main__':
    base = Path(__file__).parent
    read = lambda f: json.loads((base / f).read_text())
    print(json.dumps(compare(read('evidence-B.json'), read('evidence-C.json'),
                             read('baseline-before-serializer-B.json')), indent=2))
