<?php

namespace NixfilePlugin\Helper;

use ZipArchive;

class Backup {
	public static function register(): void {
		if ( ! wp_next_scheduled( 'nixfile_daily_backup' ) ) {
			wp_schedule_event( time(), 'daily', 'nixfile_daily_backup' );
		}
		add_action( 'nixfile_daily_backup', [ self::class, 'run' ] );
	}

	public static function run(): void {
		$uploadDir = wp_upload_dir()['basedir'] . '/nixfile-backup';
		if ( ! file_exists( $uploadDir ) ) {
			wp_mkdir_p( $uploadDir );
		}
		$timestamp   = date( 'Y-m-d-H-i-s' );
		$innerBackup = $uploadDir . "/backup-$timestamp.zip";
		$zipInner    = new \ZipArchive();
		if ( $zipInner->open( $innerBackup, \ZipArchive::CREATE ) !== true ) {
			error_log( "Backup Error: cannot create inner backup zip" );

			return;
		}
		self::addFolderToZip( WP_CONTENT_DIR, $zipInner );
		$zipInner->addFromString( "database.sql", self::dumpDatabase() );
		$zipInner->close();
		$packageZip = $uploadDir . "/backup-package-$timestamp.zip";
		$zipPackage = new \ZipArchive();
		if ( $zipPackage->open( $packageZip, \ZipArchive::CREATE ) !== true ) {
			error_log( "Backup Error: cannot create package zip" );

			return;
		}
		$zipPackage->addFile( $innerBackup, "backup-$timestamp.zip" );
		$installerPath = __DIR__ . '/installer.php';
		if ( file_exists( $installerPath ) ) {
			$zipPackage->addFile( $installerPath, "installer.php" );
		} else {
			error_log( "Backup Error: installer.php not found at $installerPath" );
		}
		$zipPackage->close();
		if ( file_exists( $innerBackup ) ) {
			unlink( $innerBackup );
		}
		error_log( "Backup package created: $packageZip" );
	}

	private static function addFolderToZip( $folder, ZipArchive $zip ) {
		$listener = new \RecursiveIteratorIterator(
			new \RecursiveDirectoryIterator( $folder, \FilesystemIterator::SKIP_DOTS ),
		);
		foreach ( $listener as $file ) {
			if ( $file->isFile() ) {
				$path      = $file->getPathname();
				$localPath = "wp-content/" . substr( $path, strlen( WP_CONTENT_DIR ) + 1 );
				$zip->addFile( $path, $localPath );
			}
		}
	}

	private static function dumpDatabase() {
		global $wpdb;
		$sql = '';
		foreach ( $wpdb->get_col( "SHOW TABLES" ) as $table ) {
			$create = $wpdb->get_row( "SHOW CREATE TABLE `$table`", ARRAY_N );
			$sql    .= "\n\n" . $create[1] . ";\n\n";
			$rows   = $wpdb->get_results( "SELECT * FROM `$table`", ARRAY_A );
			foreach ( $rows as $row ) {
				$vals = array_map( function ( $value ) {
					return is_null( $value ) ? "NULL" : "'" . esc_sql( $value ) . "'";
				}, array_values( $row ) );
				$sql  .= "INSERT INTO `$table` VALUES (" . implode( ",", $vals ) . ");\n";
			}
		}

		return $sql;
	}
}