#!/usr/bin/env python3
"""Ten Coupon admin keys: real CRUD and source-verified decimal response fix."""
import hashlib
from pathlib import Path
import subprocess
import sys
import integrate_20261010 as tool

E = tool.AI + 'parallel-ai-coupon-admin-config-20261010/'

def verify():
    folder = tool.ROOT / E
    args = [str(folder / 'evidence' / name) for name in ['B-red', 'B-green', 'C-red', 'C-green']]
    subprocess.run([sys.executable, str(folder / 'compare.py'), *args, '--map-owned-auto-time'],
        check=True, capture_output=True)
    subprocess.run([sys.executable, str(folder / 'test_compare.py'), *args], check=True, capture_output=True)
    result = tool.load(E + 'results.json')
    assert result['status'] == 'pass' and result['methods_observed'] == 10
    assert result['red_pairs'] == 18 and result['red_type_differences'] == 24
    assert result['green_pairs'] == result['green_pass'] == 10
    assert result['mapping']['source_verified_auto_times'] is True
    cleanup = tool.load(E + 'RESOURCE_POSTCHECK.json')
    for lane, port in [('B', 18361), ('C', 18362)]:
        info = result['lanes'][lane]
        assert info['natural_unchanged'] and info['user_coupon_unchanged'] and info['external_attempts'] == 0
        assert len(info['retained_owned']) == 2 and all(r['is_delete'] == 1 for r in info['retained_owned'])
        assert cleanup[lane] == {f'port_{port}_listening':False, 'private_cache_files':0, 'state_file_exists':False}
        for relative, expected in info['source_sha256'].items():
            actual = tool.ROOT.parent / 'zhctproject' / 'ai_api' / relative
            assert hashlib.sha256(actual.read_bytes()).hexdigest() == expected

def targets():
    return [dict(repo='ai_api', method='GET' if action in ['list', 'detail'] else 'POST',
        path=f'/{app}/market.Coupon/{action}', module='优惠券管理配置',
        terminal='PC端' if app == 'store' else '设备端-后端HTTP实测无物理客户端证明',
        role='private-synthetic-admin-owned-coupon-tenant', risk='read' if action in ['list', 'detail'] else 'coupon-config-write',
        scope='ai-primary-own-coupon-only-no-issuance-use-payment-or-user-write', evidence=E + 'REPORT.md',
        request_type='GET-query' if action in ['list', 'detail'] else 'POST-JSON-form-current-PC-contract',
        parity='partial-evidence-18-original-pairs-ten-green-pairs-three-DECIMAL-fields-restored-ID-trace-source-auto-time-mapped',
        cleanup='retained-two-owned-softdeleted-coupons-per-engine-private-token-cache-state-worker-released',
        boundary_empty_min_max='partial-evidence-nonempty-list-detail-expiry10-20-applyrange10-20-NULL-JSON-and-decimal-source-values')
        for app in ['store', 'terminal'] for action in ['list', 'detail', 'add', 'edit', 'delete']]

if __name__ == '__main__':
    tool.main(targets(), Path(__file__).with_name('integration-20261010-batch15.json'), verify)
