#!/usr/bin/env python3
"""Offline verification of private originals; never performs HTTP or database writes."""
import hashlib
import json
from pathlib import Path

ROOT = Path(__file__).parent
PRIVATE = ROOT / 'private-evidence'
LABELS = [f'N-{side}{step}' for side in ('P', 'M') for step in range(1, 6)] + [f'M{i}' for i in range(1, 6)]
MARKER = 'CDXCCFF927311'

def read(path):
    return json.loads(path.read_text())

def check(ok, why):
    if not ok:
        raise AssertionError(why)

summary = {'approved_HTTP': 0, 'guard_rejected_HTTP': 0, 'actual_DML': 0, 'framework_prepared': 0, 'lanes': {}, 'differences': []}
for lane in ('B', 'C'):
    directory = PRIVATE / lane
    baseline, lease = read(directory / 'baseline.json'), read(directory / 'lease.json')
    ids = {table: {str(row['id']) for row in lease[table]} for table in ('nutrition_category', 'material_category')}
    cases = []
    for label in LABELS:
        wire = read(directory / f'{label}.wire.json')
        result = read(directory / f'{label}.result.json')
        body = json.loads(wire['body'])
        check(wire['status'] == result['HTTP'] == 200, f'{lane}/{label} HTTP')
        check(isinstance(body['code'], int) and isinstance(body['message'], str) and isinstance(body['data'], list), f'{lane}/{label} response types')
        check(wire['body'] == result['body'] and hashlib.sha256(wire['body'].encode()).hexdigest() == result['body_sha256'], 'Original response bytes')
        check(wire['source_after'] == result['independent_after'], 'Independent PDO after')
        for when in ('source_before', 'source_after'):
            source = wire[when]
            for key in ('staff_sha256', 'user_sha256', 'actor_sha256'):
                check(source[key] == baseline[key], f'Original identity {lane}/{label}')
            for table in ids:
                natural = [row for row in source[table] if str(row['id']) not in ids[table]]
                check(natural == baseline[table], f'All original and read9 rows {lane}/{label}/{when}/{table}')
        dml = [sql for sql in wire['prepared_SQL'] if sql['queryString'].lstrip().split(' ')[0].upper() in ('INSERT', 'UPDATE', 'DELETE')]
        check(all(sql.get('ok') is True for sql in dml), f'All actual DML completed {lane}/{label}')
        check(wire['remaining_allowances'] == [], f'Exact write plan consumed {lane}/{label}')
        check(len(dml) == result['dml_count'], 'DML accounting')
        expected_code = 1 if lane == 'B' and label in ('N-P4', 'N-M4') else 0
        check(body['code'] == expected_code, f'Actual baseline code {lane}/{label}')
        cases.append({'label': label, 'path': wire['path'], 'code': body['code'], 'message': body['message'], 'DML': len(dml), 'rowCounts': [sql['rowCount'] for sql in dml], 'original_rows_stable': True})
        summary['approved_HTTP'] += 1
        summary['actual_DML'] += len(dml)
        summary['framework_prepared'] += len(wire['prepared_SQL'])
    final = read(directory / 'final.json')
    check(final['own_nutrition_count'] == 0 and final['own_material_count'] == 3 and final['all_material_softdeleted'], 'Final retention')
    for rejected in directory.glob('*-gate-rejected.wire.json'):
        evidence = read(rejected)
        check(evidence['source_before'] == evidence['source_after'], 'Rejected HTTP0 database changes')
        check(not any(sql.get('ok') for sql in evidence['prepared_SQL'] if sql['queryString'].startswith(('INSERT', 'UPDATE', 'DELETE'))), 'Rejected DML never executed')
        summary['guard_rejected_HTTP'] += 1
    material = read(directory / 'M4.wire.json')
    timestamps = []
    for old in material['source_before']['material_category']:
        if str(old['id']) in ids['material_category']:
            new = next(row for row in material['source_after']['material_category'] if row['id'] == old['id'])
            timestamps.append({'suffix': new['name'].removeprefix(MARKER + '-'), 'before': old['update_time'], 'after': new['update_time'], 'advanced': new['update_time'] > old['update_time']})
    summary['lanes'][lane] = {'cases': cases, 'material_move_update_time': timestamps, 'final_nutrition': 0, 'final_material_softdeleted': 3, 'all_natural_read9_identity_stable': True}
for label in ('N-P4', 'N-M4'):
    summary['differences'].append({'label': label, 'kind': 'real_response_rowCount_difference', 'B': {'code': 1, 'rowCount': 0}, 'C': {'code': 0, 'rowCount': 1}, 'status': 'FAIL_DM_COMPAT'})
summary['differences'].append({'label': 'M4', 'kind': 'material_update_time_storage', 'B_advanced': all(item['advanced'] for item in summary['lanes']['B']['material_move_update_time']), 'C_advanced': any(item['advanced'] for item in summary['lanes']['C']['material_move_update_time']), 'status': 'FAIL_DM_COMPAT'})
check(summary['approved_HTTP'] == 30 and summary['actual_DML'] == 36 and summary['guard_rejected_HTTP'] == 1, 'Exact totals')
print(json.dumps(summary, ensure_ascii=False, indent=2))
