<?php
/**
 * Uninstall script for Blaminhor Essentials
 *
 * This file is executed when the plugin is deleted from WordPress.
 * It removes all plugin data if the user has enabled the option.
 *
 * @package BlaminhorEssentials
 */

// Exit if accessed directly or not uninstalling.
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
	exit;
}

/**
 * Main uninstall function - encapsulated to avoid global variable prefix warnings.
 */
function blaminhor_essentials_uninstall() {
	global $wpdb;

	// Check if user wants to delete data.
	$blaminhor_delete_data = get_option( 'blaminhor_essentials_delete_data', false );

	if ( ! $blaminhor_delete_data ) {
		return;
	}

	// =====================================================
	// 1. Delete all plugin options
	// =====================================================
	$blaminhor_options_to_delete = array(
		'blaminhor_essentials_options',
		'blaminhor_essentials_active_modules',
		'blaminhor_essentials_delete_data',
		'blaminhor_essentials_pending_redirects',
		'blaminhor_essentials_sitemap_rules_flushed',
		'blaminhor_essentials_smtp_db_version',
		'blaminhor_essentials_broken_links_db_version',
		'ap_fer_last_error',
	);

	foreach ( $blaminhor_options_to_delete as $blaminhor_option ) {
		delete_option( $blaminhor_option );
	}

	// Delete all module settings (pattern: blaminhor_essentials_module_*).
	// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Uninstall cleanup.
	$blaminhor_module_options = $wpdb->get_col(
		$wpdb->prepare(
			"SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE %s",
			'blaminhor_essentials_module_%'
		)
	);

	foreach ( $blaminhor_module_options as $blaminhor_option ) {
		delete_option( $blaminhor_option );
	}

	// =====================================================
	// 2. Delete custom database tables
	// =====================================================

	// SMTP logs table.
	// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange -- Uninstall cleanup.
	$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}blaminhor_smtp_logs" );

	// Broken links table.
	// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange -- Uninstall cleanup.
	$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}blaminhor_broken_links" );

	// Redirections table.
	// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange -- Uninstall cleanup.
	$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}blaminhor_redirections" );

	// =====================================================
	// 3. Delete post meta
	// =====================================================

	// SEO meta data.
	// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Uninstall cleanup.
	$wpdb->query(
		$wpdb->prepare(
			"DELETE FROM {$wpdb->postmeta} WHERE meta_key LIKE %s",
			'_blaminhor_seo_%'
		)
	);

	// =====================================================
	// 4. Delete term meta
	// =====================================================

	// SEO term meta.
	// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Uninstall cleanup.
	$wpdb->query(
		$wpdb->prepare(
			"DELETE FROM {$wpdb->termmeta} WHERE meta_key LIKE %s",
			'_blaminhor_seo_%'
		)
	);

	// Post Types Order term meta.
	// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Uninstall cleanup.
	$wpdb->query(
		$wpdb->prepare(
			"DELETE FROM {$wpdb->termmeta} WHERE meta_key = %s",
			'blaminhor_menu_order'
		)
	);

	// =====================================================
	// 5. Delete transients
	// =====================================================

	// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Uninstall cleanup.
	$wpdb->query(
		$wpdb->prepare(
			"DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s",
			'_transient_blaminhor_%',
			'_transient_timeout_blaminhor_%'
		)
	);

	// =====================================================
	// 6. Delete upload directory
	// =====================================================
	$blaminhor_upload_dir        = wp_upload_dir();
	$blaminhor_plugin_upload_dir = trailingslashit( $blaminhor_upload_dir['basedir'] ) . 'blaminhor-essentials';

	if ( is_dir( $blaminhor_plugin_upload_dir ) ) {
		blaminhor_essentials_delete_directory( $blaminhor_plugin_upload_dir );
	}

	// =====================================================
	// 7. Clear any scheduled cron events
	// =====================================================
	$blaminhor_cron_hooks = array(
		'blaminhor_essentials_broken_links_scan',
		'blaminhor_essentials_db_optimize',
		'blaminhor_essentials_backup_scheduled',
	);

	foreach ( $blaminhor_cron_hooks as $blaminhor_hook ) {
		$blaminhor_timestamp = wp_next_scheduled( $blaminhor_hook );
		if ( $blaminhor_timestamp ) {
			wp_unschedule_event( $blaminhor_timestamp, $blaminhor_hook );
		}
	}

	// Clear all events with the hook pattern.
	$blaminhor_cron = get_option( 'cron' );
	if ( is_array( $blaminhor_cron ) ) {
		$blaminhor_updated = false;
		foreach ( $blaminhor_cron as $blaminhor_ts => $blaminhor_events ) {
			if ( ! is_array( $blaminhor_events ) ) {
				continue;
			}
			foreach ( $blaminhor_events as $blaminhor_hook_name => $blaminhor_args ) {
				if ( strpos( $blaminhor_hook_name, 'blaminhor_essentials' ) === 0 ) {
					unset( $blaminhor_cron[ $blaminhor_ts ][ $blaminhor_hook_name ] );
					$blaminhor_updated = true;
				}
			}
			// Remove empty timestamp.
			if ( empty( $blaminhor_cron[ $blaminhor_ts ] ) ) {
				unset( $blaminhor_cron[ $blaminhor_ts ] );
			}
		}
		if ( $blaminhor_updated ) {
			update_option( 'cron', $blaminhor_cron );
		}
	}

	// =====================================================
	// 8. Flush rewrite rules (for sitemap)
	// =====================================================
	flush_rewrite_rules();
}

/**
 * Recursively delete a directory and its contents using WP_Filesystem.
 *
 * @param string $dir Directory path.
 * @return bool
 */
function blaminhor_essentials_delete_directory( $dir ) {
	global $wp_filesystem;

	if ( ! is_dir( $dir ) ) {
		return false;
	}

	// Initialize WP_Filesystem.
	if ( ! function_exists( 'WP_Filesystem' ) ) {
		require_once ABSPATH . 'wp-admin/includes/file.php';
	}

	WP_Filesystem();

	if ( ! $wp_filesystem ) {
		// Fallback: use native PHP functions if WP_Filesystem fails.
		$blaminhor_files = array_diff( scandir( $dir ), array( '.', '..' ) );

		foreach ( $blaminhor_files as $blaminhor_file ) {
			$blaminhor_path = trailingslashit( $dir ) . $blaminhor_file;

			if ( is_dir( $blaminhor_path ) ) {
				blaminhor_essentials_delete_directory( $blaminhor_path );
			} else {
				wp_delete_file( $blaminhor_path );
			}
		}

		// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_rmdir -- Fallback when WP_Filesystem unavailable.
		return rmdir( $dir );
	}

	// Use WP_Filesystem to delete directory recursively.
	return $wp_filesystem->rmdir( $dir, true );
}

// Run uninstall.
blaminhor_essentials_uninstall();
