#!/usr/bin/env python3
"""Query/refund partial parity; MySQL barcodePay remains unproven."""
import hashlib
import json
from pathlib import Path
import subprocess
import integrate_20261010 as tool
from integrate_20261011_batches46_48 import item
from integrate_20261013_batch202 import shape

HERE = Path(__file__).resolve().parent
PRIVATE = Path('/Users/wiscourper/Documents/workspace/zhct/worktrees/dm8-compat-20261012/private-prepay-harness/batch211-internal-payment')
BASE = 'work_ai_api/2026-09-30-dm8-interface-acceptance/parallel-internal-payment-20261013/'
SUCCESS = {
    'B': ['recover-query', 'refund', 'refund-repeat', 'query-refunded', 'refund-repeat-fixed'],
    'C': ['internal-pay-v5', 'query-success', 'pay-repeat', 'refund', 'refund-repeat', 'query-refunded', 'refund-repeat-fixed'],
}


def verify():
    manifest = PRIVATE / 'ROOT211_SEAL.json'
    assert hashlib.sha256(manifest.read_bytes()).hexdigest() == 'efa81794170c7fa2d000fc6a4c74ab59c5b0da7348fc3e6597f80020bc6caf5d'
    files = json.loads(manifest.read_text())['files']
    assert len(files) == 183
    for row in files:
        path = PRIVATE / row['path']
        assert path.is_file() and not path.is_symlink()
        raw = path.read_bytes()
        assert len(raw) == row['bytes'] and hashlib.sha256(raw).hexdigest() == row['sha256']
    final = json.loads(subprocess.check_output(['/opt/homebrew/opt/php@7.4/bin/php', str(PRIVATE / 'verify_211_final_offline.php')]))
    old_c = json.loads(subprocess.check_output(['/opt/homebrew/opt/php@7.4/bin/php', str(PRIVATE / 'verify_C_six_http_offline.php')]))
    assert final['checks'] == 84 and not final['B_barcodePay_success'] and old_c['offline_checks'] == 55
    bodies = {}; receipts = {}; counts = {'B': 0, 'C': 0}
    stems = [(lane, lane + '-211-' + step, step) for lane, steps in SUCCESS.items() for step in steps]
    stems += [('B', stem, 'tool-history') for stem in ['B-211-internal-pay', 'B-211-internal-pay-v2', 'B-211-internal-pay-v3', 'B-211b-internal-pay', 'B-211c-internal-pay']]
    stems += [('C', 'C-211-internal-pay-' + version, 'tool-history') for version in ('v3', 'v4')]
    for lane, stem, step in stems:
        raw = (PRIVATE / (stem + '.raw')).read_bytes()
        receipt = json.loads((PRIVATE / (stem + '-receipt.json')).read_text())
        assert hashlib.sha256(raw).hexdigest() == receipt['raw_sha256']
        assert len(raw) == receipt['raw_bytes']
        assert receipt.get('actual_http_count', receipt.get('actual_original_http')) == 1
        counts[lane] += 1
        if raw:
            body = json.loads(raw)
            assert shape(body) == shape(receipt['json']) and body == receipt['json']
        if step == 'tool-history':
            assert not raw or body['status'] != 200
            continue
        assert receipt['http_status'] == body['status'] == 200
        before, after = receipt['before'], receipt['after']
        for key in ('order_sha256', 'order_hashes', 'store_user_sha256', 'ai_user_sha256'):
            if key in before: assert before[key] == after[key]
        if 'trade_hashes' in before:
            for key in ('593', '594'): assert before['trade_hashes'][key] == after['trade_hashes'][key]
        body.pop('trace_id'); bodies[lane, step] = body; receipts[lane, step] = receipt
    assert counts == {'B': 10, 'C': 9}
    fixed = {}
    for lane in ('B', 'C'):
        body = bodies[lane, 'refund-repeat-fixed']
        source = receipts[lane, 'refund-repeat-fixed']['after']
        refund = source['own_refunds' if lane == 'B' else 'refunds'][0]
        data = body['data']
        assert isinstance(data, dict) and set(data) == {'refund_id', 'trade_id', 'refund_no', 'refund_amount', 'status'}
        for key in ('refund_id', 'trade_id'):
            assert type(data[key]) is int and data[key] == int(refund[key])
        assert data['refund_no'] == refund['refund_no'] and data['refund_amount'] == '0.10' and data['status'] == 'SUCCESS'
        normalized = json.loads(json.dumps(body))
        for key in ('refund_id', 'trade_id', 'refund_no'): normalized['data'][key] = 'SOURCE_VERIFIED_' + key
        fixed[lane] = normalized
    assert shape(fixed['B']) == shape(fixed['C']) and fixed['B'] == fixed['C']


if __name__ == '__main__':
    audit = HERE / 'integration-20261013-batch211.json'
    assert not audit.exists(), 'Do not replay matrix integration'
    specs = [item('ai_api', 'POST', '/api/InternalPayment/' + action, BASE,
        success_case='partial-evidence-original-own-query-refund-and-terminal-retries-strict-simulated-gateway',
        readback='tested-pass-own-AI-trade-refund-transitions-Store-orders-and-users-protected-not-Store-settlement',
        parity='partial-evidence-whole-original-refund-JSON-scale-fixed-DM-only-source-verified-identities',
        cleanup='marked-rows-retained-private-runtime-retained-no-real-bank-no-Store-settlement')
        for action in ('query', 'refund')]
    specs.append(item('ai_api', 'POST', '/api/InternalPayment/pay', BASE,
        mysql_state='limited-private-tool-interrupted-no-successful-barcodePay',
        dm_state='tested-pass',
        mysql_readback='limited-owned-NOTPAY-trades-persisted-no-barcode-gateway-success',
        dm_readback='tested-pass-own-simulated-gateway-trade-I1-state20',
        success_case='partial-evidence-DM-only-original-pay-MySQL-success-still-unproven',
        readback='partial-evidence-DM-own-success-MySQL-tool-interruption-original-history-retained',
        parity='limited-no-dual-positive-barcodePay-acceptance',
        cleanup='marked-rows-retained-private-runtime-retained-real-gateway-zero'))
    tool.main(specs, audit, verify)
