#!/usr/bin/env bash
set -euo pipefail

project_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
timestamp="$(date +%Y%m%d-%H%M%S)"
output="${1:-${project_root}/../irent-release-${timestamp}.zip}"

python3 - "$project_root" "$output" <<'PACKAGE'
from pathlib import Path
import os
import sys
import zipfile

root = Path(sys.argv[1]).resolve()
output = Path(sys.argv[2]).resolve()
if output.exists():
    raise SystemExit(f"Release already exists: {output}")
if not (root / 'public/build/manifest.json').is_file():
    raise SystemExit('Build frontend assets before packaging.')

excluded_dirs = {
    '.git', '.codex', '.agents', '.aws', '.idea', '.vscode', '__MACOSX',
    '.playwright-cli', '.well-known', '.phpunit.cache', 'a_backup',
    'node_modules', 'output', 'code', 'cgi-bin', 'tests',
}
runtime_dirs = (
    'storage/app/', 'storage/logs/', 'storage/framework/cache/data/',
    'storage/framework/sessions/', 'storage/framework/views/',
    'storage/framework/testing/', 'public/storage/',
)
required_dirs = [
    'bootstrap/cache/', 'storage/app/private/', 'storage/app/public/',
    'storage/framework/cache/data/', 'storage/framework/sessions/',
    'storage/framework/views/', 'storage/framework/testing/', 'storage/logs/',
]

def include(path):
    rel = path.relative_to(root).as_posix()
    name = path.name
    if path.is_symlink():
        return False
    if any(part in excluded_dirs or part == '.DS_Store' or part.startswith('._') for part in path.relative_to(root).parts):
        return False
    if name.startswith('.env') and name != '.env.example':
        return False
    if name in {'.phpunit.result.cache', 'error_log', 'phpunit.xml', 'cpanel-diagnose.php'}:
        return False
    if rel.startswith(runtime_dirs) and name != '.gitignore':
        return False
    if rel.startswith('database/factories/') or (rel.startswith('bootstrap/cache/') and path.suffix == '.php'):
        return False
    if rel == 'public/hot':
        return False
    if path.suffix.lower() in {'.log', '.zip', '.gz', '.tar', '.sqlite', '.sqlite3', '.db'}:
        return False
    if path.suffix.lower() == '.sql' and not rel.startswith('database/schema/'):
        return False
    return True

output.parent.mkdir(parents=True, exist_ok=True)
with zipfile.ZipFile(output, 'x', zipfile.ZIP_DEFLATED, compresslevel=9) as archive:
    for parent, dirs, files in os.walk(root, followlinks=False):
        dirs[:] = sorted(d for d in dirs if d not in excluded_dirs and not (Path(parent) / d).is_symlink())
        for name in sorted(files):
            path = Path(parent) / name
            if include(path):
                archive.write(path, path.relative_to(root).as_posix())
    for directory in required_dirs:
        entry = zipfile.ZipInfo(directory)
        entry.external_attr = (0o40755 << 16) | 0x10
        archive.writestr(entry, b'')

with zipfile.ZipFile(output) as archive:
    bad = archive.testzip()
    if bad:
        raise SystemExit(f'Invalid ZIP member: {bad}')
    for info in archive.infolist():
        if not info.is_dir() and not include(root / info.filename):
            raise SystemExit(f'Unexpected runtime file in release: {info.filename}')
print(f'Created clean production release: {output}')
PACKAGE
