#!/usr/bin/env python3
"""Single-writer integration of verified read7 and four archive CRUD modules.

Batch23 needs six private evidence directories as arguments; do not copy natural
response bodies into Git. Original transition audits must never be overwritten.
"""
import hashlib
import json
from pathlib import Path
import subprocess
import sys
import integrate_20261010 as tool

READ=tool.STORE+'parallel-store-device-menu-read7-20261010/'
SPORT=tool.STORE+'parallel-store-sport-archive-crud-20261010/'
GRADE=tool.STORE+'parallel-store-grade-judgment-crud-20261010/'
SHAS={
    'DateMenu':'4749b69e8e4de3cfd0c05eb4be1a9cf182a7a22182d7c020a9cd48c60f7e44e3',
    'Equipment':'36b6016d6c4bd6a12bbe0bf2c0a483775303c5b22d1791dcb0fa6832b07738b9',
    'SportEducation':'85d98e784745b2b1f83700c703203fc2fc2657d1ec5f0b49cc3533214d1f3383',
    'SportExperience':'0a531a2650d2f382d08bb2c972a0f3303bc778f510ea6bd6fdf7a09c68854236',
    'GradeEstimation':'83802bbb20dfdd10c8fad447feca7ea5fadea6dc120db088ddf58bfdc187863e',
    'JudgmentRank':'a23132bae92876bdded3d0af002de0cecac0a188216a34f9df0b5492b47968ca',
}

def source_ok(*classes):
    for name in classes:
        p=tool.ROOT.parent/'zhctproject/store/application/p/logic'/ (name+'.php')
        assert hashlib.sha256(p.read_bytes()).hexdigest()==SHAS[name], name+' main source differs from HTTP-tested candidate'

def run(relative,*args):
    return subprocess.run([sys.executable,str(tool.ROOT/relative),*args],check=True,capture_output=True,text=True)

def verify_read(paths):
    assert len(paths)==6, 'six private red/green/runtime directories required'
    source_ok('DateMenu','Equipment')
    result=json.loads(run(READ+'verify.py',*paths).stdout)
    assert result['status']=='pass' and result['dual_engine_positive_methods']==5 and result['limited_methods']==2
    assert not result['global_wide_decimal_p0_closed'] and not result['sql_fingerprint_classification_gate_closed']
    run(READ+'test_verify.py',*paths)
    runtime=tool.load(READ+'RUNTIME_METHODS.json')['rows']
    assert len(runtime)==14 and all(r['runtime_dispatch_verified'] and r['method']=='POST' for r in runtime)

def verify_archive(relative,classes):
    source_ok(*classes)
    run(relative+'compare.py')

def common(path,evidence,scope,**extra):
    return dict(repo='store',method='POST',path=path,module='Store数据库兼容实测',
        terminal='PC-or-explicit-backend-candidate-see-report',role='isolated-owned-test-context',
        risk='read-or-owned-archive-write-see-report',scope=scope,evidence=evidence+'REPORT.md',
        request_type='current-PC-form-or-actual-controller-form-see-report',**extra)

def read_targets():
    out=[]
    for path in ['/p/dateMenu/getDishes','/p/dateMenu/getRecipeInfo','/p/date_menu/hardwareInfo',
                 '/p/dateMenu/checkMenuList','/p/equipment/VersionList','/p/equipment/versionRead','/p/equipment/consumeList']:
        x=common(path,READ,'store-primary-source-readonly-owned-disabled-actor',
            parity='partial-evidence-each-original-table-projection-and-type-verified-natural-values-not-cross-normalized',
            cleanup='retained-disabled-owned-actor-zero-funds-natural-user-projection-unchanged-private-workers-cache-reclaimed')
        if path.endswith('getRecipeInfo'):
            x.update(register_new_runtime_key=True,runtime_observed_method='POST',
                runtime_client_source='public/static/src/view/cateringManagement/modifyMenu.vue:1182',
                runtime_controller_source='application/p/controller/DateMenu.php:498')
        else:
            x.update(from_repo='unreviewed',from_source='apifox-2026-05-08')
        if path.endswith('getDishes'):
            x['verified_source_case_aliases']=['/p/DateMenu/getDishes','/p/dateMenu/getDishes']
        if path in ['/p/date_menu/hardwareInfo','/p/dateMenu/checkMenuList']:
            x.update(mysql_state='tested-pass',dm_state='partial-evidence-empty-result-only',
                success_case='partial-evidence-B-nonempty-C-empty-not-positive-C-branch',
                dm_readback='partial-evidence-original-source-empty-no-dml',
                parity='partial-evidence-original-empty-shape-and-envelope-only-C-nonempty-unverified')
        out.append(x)
    return out

def archive_targets(relative,modules):
    return [common('/p/'+module+'/'+action,relative,'store-primary-owned-archive-only-staff-user-identity-read-no-finance',
        parity='partial-evidence-complete-wire-source-pairs-original-B-wire-unchanged-DM-create-by32-and-info-time',
        cleanup='owned-records-removed-by-formal-delete-API-original-small-tables-and-identity-projection-unchanged-resources-reclaimed',
        boundary_empty_min_max='partial-evidence-valid-date-CLOB-quoted-Chinese-missing-info-see-report-validation-gaps-open')
        for module in modules for action in ['add','update','delete','info','lists']]

if __name__=='__main__':
    private=sys.argv[1:]
    batches=[(23,read_targets(),lambda:verify_read(private)),
        (25,archive_targets(SPORT,['sportEducation','sportExperience']),lambda:verify_archive(SPORT,['SportEducation','SportExperience'])),
        (26,archive_targets(GRADE,['gradeEstimation','judgmentRank']),lambda:verify_archive(GRADE,['GradeEstimation','JudgmentRank']))]
    for n,_,verify in batches:
        assert not Path(__file__).with_name(f'integration-20261010-batch{n}.json').exists(), 'Do not overwrite original transition audit'
        verify()
    for n,items,verify in batches:
        tool.main(items,Path(__file__).with_name(f'integration-20261010-batch{n}.json'),verify)
