#!/usr/bin/env python3
"""Nonempty points ledger reads; native JSON object/list kinds checked independently."""
import hashlib
import json
import subprocess
from pathlib import Path
from urllib.parse import urlsplit, parse_qs
import integrate_20261010 as tool
from integrate_20261011_batches46_48 import item

HERE = Path(__file__).resolve().parent
PRIVATE = Path('/private/tmp/cdx-ai-hk-course-b.Kmdirn')
BASE = 'work_ai_api/2026-09-30-dm8-interface-acceptance/parallel-points-nonempty-read-20261012/'


def shape(value):
    if isinstance(value, dict):
        return ('object', [(key, shape(value[key])) for key in sorted(value)])
    if isinstance(value, list):
        return ('array', [shape(item) for item in value])
    return type(value).__name__


def verify():
    for name, digest in [
        ('POINTS_LOG_NONEMPTY_READ_MANIFEST_20261012.json', 'e18680b18d01480d0865ddcded7677bea687f2d3a816cdaf1319a5938950efd1'),
        ('POINTS_LOG_NONEMPTY_READ_BC_20261012.md', '58290c47a6933d012c3de8b5a2be8abce65f7fd3de50687628fce5b7443ceb95'),
        ('read_points_logs_owned.php', '8e70b38a0c08f3c23fc2ab4083455ef8147859a91ca1d6bacb08bf7fea0dd747'),
        ('verify_points_read_receipts.php', 'e56e9c29826789a5fc380507d9732ef7f42f48b7b11d89033584a1ab1562c44e'),
    ]:
        assert hashlib.sha256((PRIVATE / name).read_bytes()).hexdigest() == digest
    r = json.loads(subprocess.check_output(['/opt/homebrew/opt/php@7.4/bin/php', str(PRIVATE / 'verify_points_read_receipts.php')]))
    assert r['status'] == 'verified' and r['real_http_gets'] == 6 and r['business_dml'] == 0
    for key in ['B_C_full_response_key_json_type_and_datetime_format_parity', 'B_C_full_response_normalized_business_value_parity']:
        assert all(v['pass'] for v in r[key].values())
    trees = []
    for name in ['owned-point-read-b-21283a751ae3.json', 'C_owned_point_read_4aff33e1d524.json']:
        doc = json.loads((PRIVATE / 'runtime' / name).read_text())
        events = {e['phase']: e for e in doc['events']}
        for path, digest in events['before_http']['source_file_sha256'].items():
            assert path.startswith('app/') and '..' not in Path(path).parts
            assert hashlib.sha256((tool.source_root('ai_api') / path).read_bytes()).hexdigest() == digest
        one = {}
        for label in ['mobile', 'store', 'terminal']:
            e = events['after_http_' + label]
            url = urlsplit(e['path'])
            expected = '/api/points.Log/list' if label == 'mobile' else '/' + label + '/market.Points/log'
            assert e['method'] == 'GET' and url.path == expected
            if label != 'mobile':
                assert parse_qs(url.query)['userId'] == [str(events['before_http']['source'][label]['own_user_id'])]
            body = json.loads(e['raw_response_exact'])
            assert type(body['status']) is int and body['status'] == 200
            assert isinstance(body['data'], dict) and isinstance(body['data']['list'], dict)
            assert isinstance(body['data']['list']['data'], list) and len(body['data']['list']['data']) == 2
            one[label] = shape(body)
        trees.append(one)
    assert trees[0] == trees[1]


if __name__ == '__main__':
    audit = HERE / 'integration-20261012-batch148.json'
    assert not audit.exists()
    specs = []
    for path in ['/api/points.Log/list', '/store/market.Points/log', '/terminal/market.Points/log']:
        specs.append(item('ai_api', 'GET', path, BASE,
            risk='readonly-own-points-ledger-positive-and-zero-no-financial-write',
            readback='tested-pass-two-owned-ledger-rows-all-source-columns-sorting-and-full-row-hash',
            success_case='partial-evidence-owned-nonempty-page1-total2-values1-and0',
            parity='partial-evidence-native-JSON-object-array-and-value-types-source-matched-owned-identity-time-values-differ',
            cleanup='no-new-rows-own-full-row-hashes-unchanged-tokens-zero-external-zero'))
    tool.main(specs, audit, verify)
