<?php
/**
 * Zoventic Invoices Uninstall
 *
 * Removes all plugin data when the plugin is deleted via WordPress admin.
 */

if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
	exit;
}

global $wpdb;

// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter

/**
 * Recursively delete a directory.
 * Defined before cleanup execution so it is available when called.
 */
if ( ! function_exists( 'zinv_uninstall_delete_dir' ) ) {
	function zinv_uninstall_delete_dir( string $dir ): void {
		if ( ! is_dir( $dir ) ) {
			return;
		}
		$scanned = scandir( $dir );
		if ( ! is_array( $scanned ) ) {
			return;
		}
		$items = array_diff( $scanned, [ '.', '..' ] );
		foreach ( $items as $item ) {
			$path = $dir . DIRECTORY_SEPARATOR . $item;
			if ( is_dir( $path ) ) {
				zinv_uninstall_delete_dir( $path );
			} else {
				if ( function_exists( 'wp_delete_file' ) ) {
					wp_delete_file( $path );
				} else {
					// phpcs:ignore WordPress.WP.AlternativeFunctions.unlink_unlink
					@unlink( $path );
				}
			}
		}
		if ( is_dir( $dir ) ) {
			$remaining_scanned = scandir( $dir );
			if ( is_array( $remaining_scanned ) ) {
				$remaining = array_diff( $remaining_scanned, [ '.', '..' ] );
				if ( empty( $remaining ) ) {
					// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_rmdir
					if ( ! rmdir( $dir ) ) {
						// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
						error_log( '[Zoventic Invoices] Uninstall: could not remove directory: ' . $dir );
					}
				}
			}
		}
	}
}

function zinv_uninstall_cleanup_site(): void {
	global $wpdb;

	// Drop all 11 free plugin tables.
	$zinv_tables = [
		'zinv_clients',
		'zinv_invoices',
		'zinv_invoice_line_items',
		'zinv_estimates',
		'zinv_estimate_line_items',
		'zinv_payments',
		'zinv_activities',
		'zinv_activities_archive',
		'zinv_settings',
		'zinv_summary_cache',
		'zinv_sequences',
	];

	foreach ( $zinv_tables as $zinv_table ) {
		$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}{$zinv_table}" );
	}

	// Remove wp_options.
	$zinv_options = $wpdb->get_col(
		$wpdb->prepare(
			"SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE %s",
			$wpdb->esc_like( 'zinv_' ) . '%'
		)
	);

	foreach ( (array) $zinv_options as $zinv_option ) {
		delete_option( $zinv_option );
	}

	// Remove user meta with zinv_ prefix.
	$wpdb->query(
		$wpdb->prepare(
			"DELETE FROM {$wpdb->usermeta} WHERE meta_key LIKE %s",
			$wpdb->esc_like( 'zinv_' ) . '%'
		)
	);

	// Remove custom capabilities from all roles.
	$zinv_caps = [
		'zinv_view_dashboard',
		'zinv_manage_clients',
		'zinv_manage_invoices',
		'zinv_manage_estimates',
		'zinv_view_payments',
		'zinv_record_payments',
		'zinv_manage_settings',
	];

	$zinv_roles = wp_roles()->roles;
	foreach ( array_keys( (array) $zinv_roles ) as $zinv_role_name ) {
		$zinv_role = get_role( $zinv_role_name );
		if ( $zinv_role ) {
			foreach ( $zinv_caps as $zinv_cap ) {
				$zinv_role->remove_cap( $zinv_cap );
			}
		}
	}

	// Clear any scheduled cron events.
	wp_clear_scheduled_hook( 'zinv_daily_tasks' );
	wp_clear_scheduled_hook( 'zinv_hourly_tasks' );
	wp_clear_scheduled_hook( 'zinv_weekly_tasks' );

	// Clear Action Scheduler jobs if AS is loaded by another plugin (e.g. Pro).
	if ( function_exists( 'as_unschedule_all_actions' ) ) {
		foreach ( [
			'zinv_subscription_billing',
			'zinv_overdue_detection',
			'zinv_dunning_steps',
			'zinv_summary_refresh',
			'zinv_estimate_expiry',
			'zinv_webhook_retries',
			'zinv_activity_archival',
			'zinv_monthly_summaries',
		] as $zinv_hook ) {
			as_unschedule_all_actions( $zinv_hook );
		}
	}

	// Remove uploaded PDFs directory recursively.
	$zinv_upload_dir = wp_upload_dir();
	$zinv_pdf_dirs   = [
		$zinv_upload_dir['basedir'] . '/zoventic-invoices-private',
	];

	foreach ( $zinv_pdf_dirs as $zinv_pdf_dir ) {
		if ( is_dir( $zinv_pdf_dir ) ) {
			zinv_uninstall_delete_dir( $zinv_pdf_dir );
		}
	}
}

if ( is_multisite() ) {
	$zinv_sites = get_sites( [ 'fields' => 'ids' ] );
	foreach ( (array) $zinv_sites as $zinv_site_id ) {
		switch_to_blog( (int) $zinv_site_id );
		zinv_uninstall_cleanup_site();
		restore_current_blog();
	}
} else {
	zinv_uninstall_cleanup_site();
}

// phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
