<?php
/**
 * Build deploy zip for HostNegar (excludes backups, git, caches).
 * php run-acc-build-deploy-zip.php
 */
declare(strict_types=1);

if ( PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg' ) {
	http_response_code( 403 );
	exit( "CLI only\n" );
}

$root = __DIR__;
$ts = date( 'Ymd-His' );
$staging = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'acc-deploy-' . $ts;
$zipPath = ( getenv( 'USERPROFILE' ) ?: $root ) . DIRECTORY_SEPARATOR . 'Desktop' . DIRECTORY_SEPARATOR . "acc-engine-deploy-{$ts}.zip";

$excludeDirNames = [
	'.git' => true,
	'node_modules' => true,
	'tabulator-master' => true,
	'.cursor' => true,
	'.claude' => true,
	'backups' => true, // under storage
];
$excludeFileGlobs = [
	'*.sql',
	'*.sql.gz',
	'*.rar',
	'*.7z',
	'.env',
];

function should_skip( string $rel, array $excludeDirNames ): bool {
	$rel = str_replace( '\\', '/', $rel );
	$parts = explode( '/', $rel );
	foreach ( $parts as $p ) {
		if ( isset( $excludeDirNames[ $p ] ) ) {
			return true;
		}
	}
	// storage/backups entire tree
	if ( str_starts_with( $rel, 'storage/backups' ) ) {
		return true;
	}
	if ( preg_match( '/\.(sql|sql\.gz|rar|7z)$/i', $rel ) ) {
		return true;
	}
	if ( basename( $rel ) === '.env' || str_starts_with( basename( $rel ), '.env.' ) ) {
		return true;
	}
	return false;
}

echo "Staging: {$staging}\n";
if ( is_dir( $staging ) ) {
	// cleanup leftover
}
mkdir( $staging . '/acc-engine', 0755, true );

$rii = new RecursiveIteratorIterator(
	new RecursiveDirectoryIterator( $root, FilesystemIterator::SKIP_DOTS ),
	RecursiveIteratorIterator::SELF_FIRST
);

$n = 0;
foreach ( $rii as $file ) {
	/** @var SplFileInfo $file */
	$full = $file->getPathname();
	$rel = substr( $full, strlen( $root ) + 1 );
	$relN = str_replace( '\\', '/', $rel );
	if ( should_skip( $relN, $excludeDirNames ) ) {
		continue;
	}
	// skip the staging script output itself if any
	if ( str_starts_with( $relN, 'acc-engine-deploy-' ) ) {
		continue;
	}
	$dest = $staging . '/acc-engine/' . $rel;
	if ( $file->isDir() ) {
		if ( ! is_dir( $dest ) ) {
			mkdir( $dest, 0755, true );
		}
		continue;
	}
	$dir = dirname( $dest );
	if ( ! is_dir( $dir ) ) {
		mkdir( $dir, 0755, true );
	}
	if ( ! @copy( $full, $dest ) ) {
		fwrite( STDERR, "copy fail: {$relN}\n" );
		continue;
	}
	$n++;
}

// Ensure production example DB file is present; do not ship real local db.local.php with XAMPP root
$prodDb = $staging . '/acc-engine/standalone/db.local.php';
$example = $staging . '/acc-engine/standalone/db.local.example.php';
if ( is_file( $example ) ) {
	copy( $example, $prodDb );
}
// Remove accidental XAMPP-only empty pass if copied earlier — rewrite from example
if ( is_file( $prodDb ) ) {
	// already from example
}

echo "Files copied: {$n}\n";
echo "Zipping to {$zipPath}\n";

if ( is_file( $zipPath ) ) {
	unlink( $zipPath );
}

$zip = new ZipArchive();
if ( $zip->open( $zipPath, ZipArchive::CREATE ) !== true ) {
	fwrite( STDERR, "cannot create zip\n" );
	exit( 1 );
}

$zipRoot = $staging . '/acc-engine';
$rii2 = new RecursiveIteratorIterator(
	new RecursiveDirectoryIterator( $zipRoot, FilesystemIterator::SKIP_DOTS )
);
foreach ( $rii2 as $file ) {
	if ( ! $file->isFile() ) {
		continue;
	}
	$full = $file->getPathname();
	$local = 'acc-engine/' . str_replace( '\\', '/', substr( $full, strlen( $zipRoot ) + 1 ) );
	$zip->addFile( $full, $local );
}
$zip->close();

$sizeMb = round( filesize( $zipPath ) / 1048576, 2 );
echo json_encode( [
	'success' => true,
	'zip'     => $zipPath,
	'size_mb' => $sizeMb,
	'files'   => $n,
	'hint'    => 'Upload zip to public_html, Extract, then edit standalone/db.local.php password',
], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT ) . PHP_EOL;
