#!/usr/bin/env python3
"""Mengemas KabarNikah_Siap_Upload.zip dan KabarNikah_OpenWA_Worker.zip.
Tidak menyertakan config.php, basis data, unggahan, log, cadangan, atau rahasia apa pun.
Pemakaian: python3 -I tools/package.py ROOT OUTDIR
"""
import os, sys, shutil, zipfile, tempfile, hashlib, re

ROOT, OUT = sys.argv[1], sys.argv[2]
os.makedirs(OUT, exist_ok=True)
stage = os.path.join(tempfile.mkdtemp(), 'KabarNikah')

def copytree(src, dst, skip):
    for base, dirs, files in os.walk(src):
        rel = os.path.relpath(base, src)
        rel = '' if rel == '.' else rel
        dirs[:] = [d for d in dirs if not skip(os.path.join(rel, d).replace(os.sep, '/') + '/')]
        os.makedirs(os.path.join(dst, rel), exist_ok=True)
        for f in files:
            r = os.path.join(rel, f).replace(os.sep, '/')
            p = os.path.join(base, f)
            if skip(r) or os.path.islink(p):
                continue
            shutil.copy2(p, os.path.join(dst, rel, f))

# 1) public_html
copytree(os.path.join(ROOT, 'app/public'), os.path.join(stage, 'public_html'),
         lambda r: r.endswith('asset-map.json'))
# 2) folder privat (tanpa data/rahasia)
def skip_priv(r):
    if r == 'config/config.php':
        return True
    if r.startswith('storage/') and r not in ('storage/.htaccess', 'storage/index.html', 'storage/'):
        return True
    return False
copytree(os.path.join(ROOT, 'app/kabarnikah'), os.path.join(stage, 'kabarnikah'), skip_priv)
for d in ['db', 'media', 'private', 'backups', 'logs', 'imports', 'marketing', 'cache']:
    os.makedirs(os.path.join(stage, 'kabarnikah/storage', d), exist_ok=True)
    open(os.path.join(stage, 'kabarnikah/storage', d, 'index.html'), 'w').close()
os.makedirs(os.path.join(stage, 'kabarnikah/config'), exist_ok=True)
open(os.path.join(stage, 'kabarnikah/config', 'index.html'), 'w').close()
# 3) dokumen + bukti
doc = os.path.join(stage, 'dokumen')
os.makedirs(doc, exist_ok=True)
for f in sorted(os.listdir(os.path.join(ROOT, 'deliverables'))):
    shutil.copy2(os.path.join(ROOT, 'deliverables', f), doc)
shutil.copytree(os.path.join(ROOT, 'docs/bukti'), os.path.join(doc, 'bukti'))
# 4) sumber pengembangan (pipeline build template & skrip QA) agar mudah dilanjutkan
copytree(os.path.join(ROOT, 'tools'), os.path.join(stage, 'pengembangan/tools'),
         lambda r: r.startswith('.fontcache') or r.endswith('.pyc') or '__pycache__' in r)
shutil.copy2(os.path.join(ROOT, 'PROGRESS.md'), os.path.join(stage, 'pengembangan/CATATAN_PROGRES.md'))
with open(os.path.join(stage, 'BACA_DULU.txt'), 'w', encoding='utf-8') as fh:
    fh.write("""KabarNikah 1.0.0 — paket siap unggah

1. Unggah isi folder public_html/ ke document root domain Anda.
2. Unggah folder kabarnikah/ ke LUAR document root (sejajar public_html).
3. Buka https://DOMAIN-ANDA/install dan ikuti dokumen/PANDUAN_INSTALASI.md.

Dokumen lengkap ada di folder dokumen/. Worker WhatsApp (OpenWA) ada di paket terpisah
KabarNikah_OpenWA_Worker.zip dan membutuhkan VPS/Docker.
Paket ini tidak berisi akun admin, kata sandi, kunci pembayaran, atau data pelanggan.
""")

# Pemeriksaan keamanan paket: tidak boleh ada berkas data/rahasia
bad = []
for base, _, files in os.walk(stage):
    for f in files:
        r = os.path.relpath(os.path.join(base, f), stage).replace(os.sep, '/')
        if re.search(r'\.(sqlite|sqlite3|db-wal|db-shm)$|config/config\.php$|install-code\.txt$|installed\.lock$|\.env$', r):
            bad.append(r)
if bad:
    sys.exit('BERKAS TERLARANG DI PAKET: ' + ', '.join(bad))

def zipdir(src_dir, zpath, arc_root):
    with zipfile.ZipFile(zpath, 'w', zipfile.ZIP_DEFLATED, compresslevel=6) as z:
        for base, dirs, files in os.walk(src_dir):
            dirs.sort()
            rel = os.path.relpath(base, src_dir)
            if rel != '.' and not files and not dirs:
                z.writestr(os.path.join(arc_root, rel).replace(os.sep, '/') + '/', '')
            for f in sorted(files):
                p = os.path.join(base, f)
                z.write(p, os.path.join(arc_root, os.path.relpath(p, src_dir)).replace(os.sep, '/'))

app_zip = os.path.join(OUT, 'KabarNikah_Siap_Upload.zip')
if os.path.exists(app_zip):
    os.remove(app_zip)
zipdir(stage, app_zip, 'KabarNikah')

wstage = os.path.join(tempfile.mkdtemp(), 'KabarNikah_OpenWA_Worker')
copytree(os.path.join(ROOT, 'worker'), wstage, lambda r: r == '.env')
shutil.copy2(os.path.join(ROOT, 'deliverables/PANDUAN_OPENWA.md'), wstage)
w_zip = os.path.join(OUT, 'KabarNikah_OpenWA_Worker.zip')
if os.path.exists(w_zip):
    os.remove(w_zip)
zipdir(wstage, w_zip, 'KabarNikah_OpenWA_Worker')

for z in (app_zip, w_zip):
    h = hashlib.sha256(open(z, 'rb').read()).hexdigest()
    print(os.path.basename(z), round(os.path.getsize(z) / 1048576, 1), 'MB', 'sha256', h)
