"""Package an already verified production staging tree; never include local state."""
from pathlib import Path
import hashlib, json, os, shutil, zipfile, xml.etree.ElementTree as ET

root = Path(__file__).resolve().parents[1]
stage = root / 'runtime/release-stage'
output = root.parents[1] / '08-Release-Packages/KEMET-Retail-RC1-2026-09-29'
output.mkdir(parents=True, exist_ok=True)
test = ET.parse(root / 'runtime/release-tests.xml').getroot().find('testsuite').attrib
assert int(test['errors']) == int(test['failures']) == 0
browser = json.loads((root / 'runtime/browser-validation.json').read_text(encoding='utf-8'))
assert not browser.get('failure') and not browser['errors']
summary = {'release': 'retail-rc1-2026.09.29', 'laravel': '13.33.0', 'php_tested': '8.3.35',
           'tests': int(test['tests']), 'assertions': int(test['assertions']), 'errors': 0, 'failures': 0,
           'phpunit_notices': 14, 'browser_page_checks': len(browser['checks']),
           'scope': 'local isolated validation; not a production deployment',
           'xbrl': 'Immediate internal trial balance; official filing profile not configured'}
(root / 'docs/platform/release-validation.json').write_text(json.dumps(summary, indent=2), encoding='utf-8')
shutil.copy2(root / 'runtime/browser-validation.json', root / 'docs/platform/browser-verification.json')
# Sync source edits after the Composer production install. Never replace its vendor tree.
for folder in ['app','config','custom_views','database','deploy','docs','lang','Modules','packages','public','ReceiptComponents','resources','routes','tests','tools','InvoiceGallery']:
    source = root / folder
    if source.exists(): shutil.copytree(source, stage / folder, dirs_exist_ok=True,
        ignore=shutil.ignore_patterns('node_modules','.git','uploads','__pycache__','*.log','*.sql'))
for name in ['artisan','composer.json','composer.lock','modules_statuses.json','phpunit.xml','.env.example']:
    shutil.copy2(root / name, stage / name)

archive = output / 'KEMET-Retail-L13-PHP83-RC1.zip'
entries = {}
excluded_dirs = {'.git','node_modules','__pycache__','.idea','.vscode'}
with zipfile.ZipFile(archive, 'w', zipfile.ZIP_DEFLATED, compresslevel=6, allowZip64=True) as z:
    for current, dirs, files in os.walk(stage):
        dirs[:] = sorted(d for d in dirs if d not in excluded_dirs)
        rel = Path(current).relative_to(stage)
        prefix = rel.as_posix()
        if prefix in ['runtime','storage','public/uploads','public/storage','scripts']:
            dirs[:] = []; continue
        for name in sorted(files):
            path = Path(current) / name
            target = path.relative_to(stage).as_posix()
            if (name == '.env' or name.startswith('.env.') and not name.endswith('.example')
                or name == '.phpunit.result.cache' or name.endswith(('.log','.sql','.pyc'))
                or target.startswith('bootstrap/cache/')): continue
            data = path.read_bytes()
            info = zipfile.ZipInfo(target)
            info.compress_type = zipfile.ZIP_DEFLATED
            info.external_attr = (0o755 if target == 'artisan' else 0o644) << 16
            z.writestr(info, data, compresslevel=6)
            entries[target] = hashlib.sha256(data).hexdigest()
    for directory in ['storage/app/private/','storage/app/public/','storage/framework/cache/data/','storage/framework/sessions/','storage/framework/views/','storage/logs/','public/uploads/','bootstrap/cache/']:
        info=zipfile.ZipInfo(directory);info.external_attr=(0o40755 << 16) | 0x10;z.writestr(info,b'')
    z.writestr('RELEASE-FILES.sha256', ''.join(f'{digest}  {path}\n' for path,digest in sorted(entries.items())))

with zipfile.ZipFile(archive) as z:
    assert z.testzip() is None
    names = set(z.namelist())
    assert '.env' not in names and 'vendor/autoload.php' in names
    assert not any(n.startswith(('runtime/','vendor/phpunit/','vendor/barryvdh/laravel-debugbar/')) for n in names)
    installed=json.loads(z.read('vendor/composer/installed.json'))
    assert installed.get('dev') is False
    for path,digest in entries.items(): assert hashlib.sha256(z.read(path)).hexdigest()==digest
shutil.copy2(root / 'deploy/INSTALL.ar.md', output / 'INSTALL.ar.md')
shutil.copy2(root / 'docs/platform/release-validation.json', output / 'VALIDATION.json')
hashes=[]
for name in ['KEMET-Retail-L13-PHP83-RC1.zip','KEMET-Retail-New-Database.sql','INSTALL.ar.md','VALIDATION.json']:
    path=output/name;hashes.append(f'{hashlib.sha256(path.read_bytes()).hexdigest()}  {name}\n')
(output/'SHA256SUMS.txt').write_text(''.join(hashes),encoding='ascii')
print(json.dumps({'output':str(output),'zip_files':len(entries),'zip_mib':round(archive.stat().st_size/1024/1024,2),'sql_bytes':(output/'KEMET-Retail-New-Database.sql').stat().st_size,'archive_verified':True}))
