<?php
/**
 * Storzen — Uninstall handler.
 *
 * Fired when the plugin is deleted from WordPress admin (Plugins → Delete).
 * Removes ALL options created by Storzen so no orphaned data is left in the
 * wp_options table. Deactivation does NOT run this file; only a full delete does.
 *
 * WordPress.org review requirement:
 *   "The plugin must clean up after itself. If the plugin creates options,
 *    posts, or custom tables, these must be removed on uninstall."
 *
 * What is removed:
 *  • All pk_storzen_* option keys  (admin panel / widget toggle settings)
 *  • All storzen_* option keys     (module settings)
 *  • Storzen user-meta keys        (review-notice dismiss flag, dark-mode pref)
 *  • Storzen scheduled cron events (copurchase matrix rebuild)
 *
 * What is NOT removed (intentional):
 *  • User wishlist data stored in user_meta (user-generated content — their data)
 *  • WooCommerce orders / products — Storzen never owns these
 *  • License key — removed separately on license deactivation (if Pro)
 *
 * @package storzen
 * @since   1.2.0
 */

// WordPress uninstall guard — must be present.
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
	exit;
}

// ── Remove all Storzen options ────────────────────────────────────────────────

/**
 * Option keys registered by the admin panel (pk_storzen_* prefix).
 * Keep this list in sync with the tab keys used in inc/admin-panel.php.
 */
$panel_options = array(
	// Widget tab option keys (stored by the framework as pk_storzen_widgets_*)
	'pk_storzen_widgets_shop',
	'pk_storzen_widgets_shop_details',
	'pk_storzen_widgets_cart',
	'pk_storzen_widgets_checkout',
	'pk_storzen_widgets_thankyou',
	'pk_storzen_widgets_my_account',
	'pk_storzen_widgets_landing',

	// Module settings saved by the modules panel
	'pk_storzen_modules',
	'pk_storzen_modules_settings',

	// Global / misc panel keys
	'pk_storzen_global',
	'pk_storzen_settings',
	'pk_storzen_license',
);

foreach ( $panel_options as $key ) {
	delete_option( $key );
}

// ── Remove storzen_* prefixed options (module settings) ──────────────────────

global $wpdb;

// Fetch and delete all options whose name starts with 'storzen_'.
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
$storzen_option_names = $wpdb->get_col(
	"SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE 'storzen\_%'"
);

if ( ! empty( $storzen_option_names ) ) {
	foreach ( $storzen_option_names as $option_name ) {
		delete_option( sanitize_key( $option_name ) );
	}
}

// ── Remove user meta ──────────────────────────────────────────────────────────

/**
 * Meta keys stored per-user.
 * We delete in bulk using $wpdb to avoid loading every user.
 *
 * Keys:
 *   _storzen_review_notice_dismissed  — "don't show again" flag for the review CTA
 *   _storzen_dark_mode                — admin dark mode user preference
 */
$user_meta_keys = array(
	'_storzen_review_notice_dismissed',
	'_storzen_dark_mode',
);

foreach ( $user_meta_keys as $meta_key ) {
	// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.SlowDBQuery.slow_db_query_meta_key
	$wpdb->delete( $wpdb->usermeta, array( 'meta_key' => $meta_key ), array( '%s' ) );
}

// ── Clear scheduled cron events ───────────────────────────────────────────────

$cron_hooks = array(
	'storzen_rebuild_recommendations', // Co-purchase matrix rebuild (v2.0+)
	'storzen_weekly_cleanup',
);

foreach ( $cron_hooks as $hook ) {
	$timestamp = wp_next_scheduled( $hook );
	if ( $timestamp ) {
		wp_unschedule_event( $timestamp, $hook );
	}
	wp_clear_scheduled_hook( $hook );
}

// ── Back in Stock: drop subscriber table + clean cron ────────────────────────

global $wpdb;
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.SchemaChange,WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'storzen_bis_subscribers' );

delete_option( 'storzen_bis_db_ver' );

wp_clear_scheduled_hook( 'storzen_bis_send_notifications' );

// ── Multisite: repeat for every blog ─────────────────────────────────────────

if ( is_multisite() ) {
	// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
	$blog_ids = $wpdb->get_col( "SELECT blog_id FROM {$wpdb->blogs}" );

	foreach ( $blog_ids as $blog_id ) {
		switch_to_blog( (int) $blog_id );

		foreach ( $panel_options as $key ) {
			delete_option( $key );
		}

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
		$site_option_names = $wpdb->get_col(
			"SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE 'storzen\_%'"
		);
		foreach ( $site_option_names as $option_name ) {
			delete_option( sanitize_key( $option_name ) );
		}

		// BIS table for this blog.
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.SchemaChange,WordPress.DB.DirectDatabaseQuery.NoCaching
		$wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'storzen_bis_subscribers' );
		delete_option( 'storzen_bis_db_ver' );
		wp_clear_scheduled_hook( 'storzen_bis_send_notifications' );

		restore_current_blog();
	}
}
