#!/usr/bin/env python3
"""User payment code: DB-only branch, actual interval and exact cleanup."""
import hashlib
import json
from pathlib import Path
import integrate_20261010 as tool
from integrate_20261011_batches46_48 import item
from integrate_20261012_batch119 import shape
HERE=Path(__file__).resolve().parent
P=Path('/Users/wiscourper/Documents/workspace/local/dm8-batch116-20261012.S1TtvG')
B=Path('/private/tmp/cdx-ai-qrcode-b.CJJBpC/runtime')
BASE='work_ai_api/2026-10-12-dm8-hk-course-batch/'
REPORT=BASE+'USER_QRCODE_ROOT_REVIEW.md'
FILES=[
 (B,'user-qrcode-CDXQRC8628AB0B832.json','54f638f2b541379a166263b9b06e4bffc94f51506e9e54b70467ea784e137bed'),
 (P,'user-qrcode-CDXQR3F4B7EE99C82.json','eb2a65359528c36b13c96a96daa85801795eff0931bc73c8206ba91267567637'),
 (B,'user-qrcode-redacted-CDXQRC8628AB0B832.jsonl','fd75616b48296b49a2b82668a12f8df3d4c186dded30be59e8ab909db484b5e9'),
 (P,'user-qrcode-redacted-CDXQR3F4B7EE99C82.jsonl','cd46c21a83f7472f84463348cea73565291ddced6b311f40445f7a91e565d57f'),
 (B,'qrcode-independent-posthoc-user-qrcode-CDXQRC8628AB0B832.json','9b36021f422c7eb2eb1c1224ab47c0b2a34a485a4897841dedad080c0a6ded57'),
 (P,'qrcode-independent-posthoc-user-qrcode-CDXQR3F4B7EE99C82.json','cfea2285745ca90ac4e546fe67b836775909bbd588a5814737387e4d422f502e'),
]

def verify():
    data=[]
    for root,name,pin in FILES:
        raw=(root/name).read_bytes();assert hashlib.sha256(raw).hexdigest()==pin
        data.append(json.loads(raw))
    bodies=[]
    for receipt,wire,posthoc in zip(data[:2],data[2:4],data[4:6]):
        before,after,final=receipt['events']
        assert before['private_token_present'] and before['own_type4_rows_before']==0
        assert after['http']==after['business_status']==200 and after['pass'] and after['paycode_format_valid']
        assert after['own_type4_rows_after']==1 and type(after['own_user_code_id']) is int
        assert after['start_time_pdo_type']==after['end_time_pdo_type']=='string' and after['start_end_interval_seconds']==90
        assert before['config_row_sha256']==after['config_row_sha256_after']
        assert before['upload_table_count_before']==after['upload_table_count_after']
        assert before['private_upload_file_sha256_before']==after['private_upload_file_sha256_after'] and after['stub_delta_bytes']==0
        assert final['token_absent'] and final['user_code_cleanup']=='exact_code_removed'
        assert wire['path']=='/api/User/qrcode' and wire['method']=='POST' and wire['http']==200
        assert wire['unredacted_response_sha256']==after['unredacted_response_sha256']
        body=wire['response_redacted'];assert body['status']==200
        assert type(body['data']['expires_in']) is str and body['data']['expires_in']=='60'
        assert body['data']['file_path']=='' and body['data']['paycode']=='[REDACTED]'
        body.pop('trace_id',None);bodies.append(body)
        check=posthoc['events'][0]
        for key in ['exact_created_code_id_absent','own_type4_total_zero','upload_table_total_unchanged','config_rows_hash_unchanged','private_upload_tree_unchanged','independent_new_timepoint','pass']:
            assert check[key],key
        assert check['dml']==check['business_http']==0
    assert bodies[0]==bodies[1] and shape(bodies[0])==shape(bodies[1])

if __name__=='__main__':
    audit=HERE/'integration-20261012-batch123.json';assert not audit.exists()
    targets=[item('ai_api','POST','/api/User/qrcode',BASE,evidence=REPORT,
        scope='paycode-file2-Store-user-code-DB-only-image-OSS-hard-refused-private-workers',
        success_case='partial-evidence-own-type4-payment-code-generation-no-physical-scan-or-image',
        readback='tested-pass-own-code0-to1-to0-start-end90sec-config-upload-files-unchanged',
        parity='partial-evidence-complete-redacted-response-equal-expires-in-string60-existing30sec-grace',
        cleanup='exact-own-code-ID-user-type-code-match-deleted-new-connection-own-range-zero-token-absent')]
    tool.main(targets,audit,verify)
