#!/usr/bin/env python3
"""Ten actual Onto reads plus four separate zero-boundary evidence updates."""
import hashlib
import json
from pathlib import Path
import subprocess
import sys
import integrate_20261010 as tool
from integrate_20261011_batches40_42 import sha
from integrate_20261011_batches46_48 import item

BASE = tool.STORE + 'parallel-store-onto-nutrition-read10-20261011/'
RUNNER = '''import runpy,sys
from pathlib import Path
from unittest.mock import patch
root=Path(sys.argv[1]);sys.path.insert(0,str(root))
def check_only(path,data,*args,**kwargs):
 assert path.is_file() and path.read_text()==data, 'sealed derived content changed: '+str(path)
 return len(data)
with patch.object(Path,'write_text',check_only),patch.object(Path,'chmod',lambda *a,**k:None):
 runpy.run_path(str(root/'verify.py'),run_name='__main__')
'''

def seal(root,name,pin,canonical_pin,count):
    assert sha(root/name)==pin
    manifest=json.loads((root/name).read_text())
    canonical=dict(manifest);embedded=canonical.pop('seal_sha256')
    assert embedded==canonical_pin
    assert hashlib.sha256(json.dumps(canonical,sort_keys=True,separators=(',',':')).encode()).hexdigest()==embedded
    assert len(manifest['files'])==count
    for record in manifest['files']:
        relative=Path(record['path']);assert not relative.is_absolute() and '..' not in relative.parts
        path=root/relative;assert path.is_file() and not path.is_symlink()
        assert path.stat().st_size==record['bytes'] and sha(path)==record['sha256']
        assert oct(path.stat().st_mode & 0o777)==record['mode']
        if 'private' in relative.parts:
            assert record['mode']=='0o600'
            parent=path.parent
            while parent!=root:
                # Public clientheaders contains a private subtree, not itself private.
                if parent.name=='private' or 'private' in parent.relative_to(root).parts:
                    assert not parent.is_symlink() and parent.stat().st_mode & 0o777==0o700
                parent=parent.parent

def verify():
    root=tool.ROOT/BASE
    seal(root,'manifest10.json','e541c79d86bd1c820ea6069e32a8cefefeb791616f15cfee84a38f6983dddd96',
        '5eb49db7994ef00acb548e8a84cd3fed26a5bc749b06f88721611629e084f09a',129)
    seal(root/'zero4','manifest-zero4.json','1875a2a6476b58d15dcbadede3a5a701bdc4de169d55930152beb79a8982549c',
        '5e6dae31fa23d3beeb11ac5a942b4b90aa2f52a00b5d77eeecc244d791fdf830',73)
    for relative, assertions, HTTP, mutations in [('',18745,22,10),('zero4',15615,8,4)]:
        result=subprocess.run([sys.executable,'-B','-c',RUNNER,str(root/relative)],capture_output=True,text=True)
        assert result.returncode==0,result.stderr
        report=json.loads(result.stdout)
        assert report['assertions']==assertions and report['HTTP']==HTTP and report['negative_cases']==mutations
        if relative:
            assert report['CAS']['B']['attempts']==3 and report['CAS']['B']['rollback']==1
            assert report['CAS']['C']['attempts']==2
            assert all(r['final']==166 and r['new']==18 for r in report['logs'].values())
        else:
            assert all(r['final']==148 and r['old']==97 for r in report['log_counts'].values())
            assert all(not r['full_body_is_JSON'] for r in report['original_DietaryFiber'].values())
    assert sha(root/'source-lock.json')=='57d57588410be71682c8597d092b125cb26cf2b3d489b6ce7f1a136c56bad96b'
    sources=tool.load(BASE+'source-lock.json');assert len(sources)==958
    for relative,digest in sources.items():
        assert sha(tool.ROOT.parent/'zhctproject/store/application'/relative)==digest,relative

def targets():
    plan=tool.load(BASE+'log-http-plan.json')
    result=[item('store','POST',case['path'],BASE,
        risk='fixed-owned-nutrition-reads-with-original-log-INSERTs',
        parity='partial-ten-full-body-byte-identical-pairs-original-Axios-Accept-required-for-string-HTML-response',
        boundary_empty_min_max='partial-nonzero-owned-fixture-original-calculation-behavior-preserved',
        cleanup='eight-marked-fixtures-and-owned-logs-retained-own-workers-auth-cache-removed') for case in plan['cases']]
    for case in tool.load(BASE+'zero4/log-http-plan.json')['cases']:
        result.append(item('store','POST',case['path'],BASE+'zero4/',evidence_only=True,
            parity='partial-four-real-zero-response-byte-identical-pairs-two-original-404-NaN-errors-not-success',
            boundary_empty_min_max='partial-zero-DECIMAL-type-restoration-source-errors-preserved-not-business-zero-fix',
            cleanup='full-owned-original100-restored-by-exact-CAS-all166-logs-preserved-B-tool-rollback-separate'))
    return result

if __name__=='__main__':
    audit=Path(__file__).with_name('integration-20261011-batch72.json')
    assert not audit.exists(),'Preserve original transition audit'
    tool.main(targets(),audit,verify)
