#!/usr/bin/env python3
"""Create a sanitized corresponding-source ZIP and reject credential leakage."""
from pathlib import Path
import hashlib, os, re, sys, zipfile
root=Path(__file__).resolve().parents[1]
if len(sys.argv)>1:
 version=sys.argv[1]
else:
 gradle=(root/"app"/"build.gradle").read_text(encoding="utf-8")
 match=re.search(r'versionName\s+["\']([^"\']+)',gradle)
 if not match: raise SystemExit("Could not detect versionName from app/build.gradle")
 version=match.group(1)
out=root/"artifacts"/f"Starfall-Haven-{version}-source.zip"
out.parent.mkdir(exist_ok=True)
exclude={'.git','.gradle','.idea','build','artifacts'}
secret_names={'.env','storepass','keypass','local.properties'}
secret_patterns=[
 re.compile(rb'PIXELLAB[_ -]?(API[_ -]?)?(TOKEN|KEY)\s*[:=]\s*["\']?[A-Za-z0-9._-]{16,}',re.I),
 re.compile(rb'Authorization\s*:\s*Bearer\s+[A-Za-z0-9._-]{16,}',re.I),
]
files=[]
for p in sorted(root.rglob('*')):
 if not p.is_file() or any(part in exclude for part in p.parts): continue
 if p.name in secret_names or p.suffix.lower() in {'.jks','.keystore','.apk','.aab','.idsig'}: continue
 data=p.read_bytes()
 if p.resolve()!=Path(__file__).resolve():
  for pattern in secret_patterns:
   if pattern.search(data): raise SystemExit(f"Secret-like content rejected: {p.relative_to(root)}")
 files.append((p,data))
# Ensure the archive is deterministic across identical source trees.
os.environ.setdefault('SOURCE_DATE_EPOCH','1704067200')
stamp=(2024,1,1,0,0,0)
with zipfile.ZipFile(out,'w',zipfile.ZIP_DEFLATED,compresslevel=9) as z:
 for p,data in files:
  info=zipfile.ZipInfo(str(p.relative_to(root)),stamp)
  info.compress_type=zipfile.ZIP_DEFLATED
  info.external_attr=(0o100644 << 16)
  z.writestr(info,data)
with zipfile.ZipFile(out) as z:
 bad=z.testzip()
 if bad: raise SystemExit(f"ZIP integrity failure: {bad}")
print(out)
print(hashlib.sha256(out.read_bytes()).hexdigest())
print(f"files={len(files)} bytes={out.stat().st_size}")
