<?php
/**
 * Uninstall-Routine für WP Agent Companion.
 *
 * Wird von WordPress ausgeführt, wenn das Plugin über die Admin-Oberfläche
 * gelöscht wird (nicht bei bloßer Deaktivierung).
 *
 * Fremde Inhalts-, SEO- und Builder-Daten gehören dem Kunden und bleiben
 * erhalten. Standardmäßig werden die wpagently-eigenen Optionen und alle über
 * die Verbindungsoberfläche angelegten Zugangsdaten entfernt. Administratoren
 * können vor der Deinstallation explizit OAuth- oder Application-Password-
 * Zugangsdaten sowie eigene Site-Skills oder Agent-Erinnerungen erhalten. Die Polar-Aktivierung wird hier nicht
 * über HTTP freigegeben: WordPress-Deinstallationen dürfen nicht von einem
 * externen Dienst abhängen. Sie muss vorher auf Werkzeuge > wpagently-Lizenz
 * deaktiviert werden oder kann im Polar-Kundenportal freigegeben werden.
 *
 * @package WPAgentCompanion
 */

// Direktaufruf und Aufruf außerhalb des WordPress-Uninstall-Kontexts verhindern.
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
	exit;
}

$cleanup_site = static function (): void {
	$stored_cleanup_preferences = get_option( 'wp_agent_companion_uninstall_cleanup', array() );
	$stored_cleanup_preferences = is_array( $stored_cleanup_preferences ) ? $stored_cleanup_preferences : array();
	$cleanup_preferences = array(
		'oauth'                 => is_bool( $stored_cleanup_preferences['oauth'] ?? null ) ? $stored_cleanup_preferences['oauth'] : true,
		'application_passwords' => is_bool( $stored_cleanup_preferences['application_passwords'] ?? null ) ? $stored_cleanup_preferences['application_passwords'] : true,
		'skills'                => is_bool( $stored_cleanup_preferences['skills'] ?? null ) ? $stored_cleanup_preferences['skills'] : true,
		'memory'                => is_bool( $stored_cleanup_preferences['memory'] ?? null ) ? $stored_cleanup_preferences['memory'] : true,
	);
	$connections = get_option( 'wp_agent_companion_connections', array() );
	if ( $cleanup_preferences['application_passwords'] && class_exists( 'WP_Application_Passwords' ) && is_array( $connections ) ) {
		foreach ( $connections as $connection ) {
			if ( ! is_array( $connection ) ) {
				continue;
			}
			$user_id  = absint( $connection['user_id'] ?? 0 );
			$app_uuid = is_string( $connection['app_uuid'] ?? null ) ? $connection['app_uuid'] : '';
			if ( $user_id && wp_is_uuid( $app_uuid ) ) {
				WP_Application_Passwords::delete_application_password( $user_id, $app_uuid );
			}
		}
	}

	$gravity_grants = get_option( 'wp_agent_companion_gravity_capability_grants', array() );
	if ( is_array( $gravity_grants ) ) {
		$allowed = array( 'gravityforms_edit_forms', 'gravityforms_create_form', 'gravityforms_delete_forms' );
		foreach ( $gravity_grants as $user_id => $capabilities ) {
			$user = get_user_by( 'id', absint( $user_id ) );
			if ( ! $user instanceof WP_User || ! is_array( $capabilities ) ) {
				continue;
			}
			foreach ( array_intersect( $allowed, array_map( 'sanitize_key', $capabilities ) ) as $capability ) {
				$user->remove_cap( $capability );
			}
			clean_user_cache( $user->ID );
		}
	}
	$fluent_forms_grants = get_option( 'wp_agent_companion_fluent_forms_capability_grants', array() );
	if ( is_array( $fluent_forms_grants ) ) {
		$allowed = array( 'fluentform_dashboard_access', 'fluentform_forms_manager' );
		foreach ( $fluent_forms_grants as $user_id => $capabilities ) {
			$user = get_user_by( 'id', absint( $user_id ) );
			if ( ! $user instanceof WP_User || ! is_array( $capabilities ) ) {
				continue;
			}
			foreach ( array_intersect( $allowed, array_map( 'sanitize_key', $capabilities ) ) as $capability ) {
				$user->remove_cap( $capability );
			}
			clean_user_cache( $user->ID );
		}
	}
	$formidable_grants = get_option( 'wp_agent_companion_formidable_capability_grants', array() );
	if ( is_array( $formidable_grants ) ) {
		$allowed = array( 'frm_view_forms', 'frm_edit_forms', 'frm_delete_forms' );
		foreach ( $formidable_grants as $user_id => $capabilities ) {
			$user = get_user_by( 'id', absint( $user_id ) );
			if ( ! $user instanceof WP_User || ! is_array( $capabilities ) ) {
				continue;
			}
			foreach ( array_intersect( $allowed, array_map( 'sanitize_key', $capabilities ) ) as $capability ) {
				$user->remove_cap( $capability );
			}
			clean_user_cache( $user->ID );
		}
	}
	$gravity_entry_grants = get_option( 'wp_agent_companion_gravity_entry_capability_grants', array() );
	if ( is_array( $gravity_entry_grants ) ) {
		$allowed = array( 'gravityforms_view_entries', 'gravityforms_edit_entries', 'gravityforms_delete_entries' );
		foreach ( $gravity_entry_grants as $user_id => $capabilities ) {
			$user = get_user_by( 'id', absint( $user_id ) );
			if ( ! $user instanceof WP_User || ! is_array( $capabilities ) ) {
				continue;
			}
			foreach ( array_intersect( $allowed, array_map( 'sanitize_key', $capabilities ) ) as $capability ) {
				$user->remove_cap( $capability );
			}
			clean_user_cache( $user->ID );
		}
	}
	$fluent_entry_grants = get_option( 'wp_agent_companion_fluent_forms_entry_capability_grants', array() );
	if ( is_array( $fluent_entry_grants ) ) {
		$allowed = array( 'fluentform_entries_viewer', 'fluentform_manage_entries' );
		foreach ( $fluent_entry_grants as $user_id => $capabilities ) {
			$user = get_user_by( 'id', absint( $user_id ) );
			if ( ! $user instanceof WP_User || ! is_array( $capabilities ) ) {
				continue;
			}
			foreach ( array_intersect( $allowed, array_map( 'sanitize_key', $capabilities ) ) as $capability ) {
				$user->remove_cap( $capability );
			}
			clean_user_cache( $user->ID );
		}
	}
	$wc_order_grants = get_option( 'wp_agent_companion_wc_order_capability_grants', array() );
	if ( is_array( $wc_order_grants ) ) {
		$allowed = array( 'read_private_shop_orders', 'edit_shop_orders' );
		foreach ( $wc_order_grants as $user_id => $capabilities ) {
			$user = get_user_by( 'id', absint( $user_id ) );
			if ( ! $user instanceof WP_User || ! is_array( $capabilities ) ) {
				continue;
			}
			foreach ( array_intersect( $allowed, array_map( 'sanitize_key', $capabilities ) ) as $capability ) {
				$user->remove_cap( $capability );
			}
			clean_user_cache( $user->ID );
		}
	}
	$wpforms_grants = get_option( 'wp_agent_companion_wpforms_capability_grants', array() );
	if ( is_array( $wpforms_grants ) ) {
		$allowed = array( 'wpagently_wpforms_forms_access', 'wpagently_wpforms_entries_access', 'wpagently_wpforms_write_access' );
		foreach ( $wpforms_grants as $user_id => $capabilities ) {
			$user = get_user_by( 'id', absint( $user_id ) );
			if ( ! $user instanceof WP_User || ! is_array( $capabilities ) ) {
				continue;
			}
			foreach ( array_intersect( $allowed, array_map( 'sanitize_key', $capabilities ) ) as $capability ) {
				$user->remove_cap( $capability );
			}
			clean_user_cache( $user->ID );
		}
	}
	$ninjaforms_grants = get_option( 'wp_agent_companion_ninjaforms_capability_grants', array() );
	if ( is_array( $ninjaforms_grants ) ) {
		$allowed = array( 'wpagently_ninjaforms_forms_access', 'wpagently_ninjaforms_submissions_access', 'wpagently_ninjaforms_write_access', 'wpagently_ninjaforms_delivery_access' );
		foreach ( $ninjaforms_grants as $user_id => $capabilities ) {
			$user = get_user_by( 'id', absint( $user_id ) );
			if ( ! $user instanceof WP_User || ! is_array( $capabilities ) ) {
				continue;
			}
			foreach ( array_intersect( $allowed, array_map( 'sanitize_key', $capabilities ) ) as $capability ) {
				$user->remove_cap( $capability );
			}
			clean_user_cache( $user->ID );
		}
	}

	$site_options = array(
		'wp_agent_license_state',
		'wp_agent_license_mutation_lock',
		'wp_agent_companion_enabled',
		'wp_agent_companion_bound_site',
		'wp_agent_companion_profile',
		'wp_agent_companion_disabled_abilities',
		'wp_agent_companion_trusted_external_abilities',
		'wp_agent_companion_connections',
		'wp_agent_companion_connections_lock',
		'wp_agent_companion_connection_health',
		'wp_agent_wc_bulk_price_lock',
		'wp_agent_companion_connection_diagnostics',
		'wp_agent_companion_uninstall_cleanup',
		'wp_agent_companion_gravity_capability_grants',
		'wp_agent_companion_fluent_forms_capability_grants',
		'wp_agent_companion_formidable_capability_grants',
		'wp_agent_companion_formidable_mutation_lock',
		'wp_agent_companion_fluent_forms_entry_capability_grants',
		'wp_agent_companion_gravity_entry_capability_grants',
		'wp_agent_companion_wc_order_capability_grants',
		'wp_agent_companion_wpforms_capability_grants',
		'wp_agent_companion_ninjaforms_capability_grants',
		'wp_agent_companion_oauth_codes',
		'wp_agent_companion_oauth_device_codes',
		'wp_agent_companion_oauth_lock',
		'wp_agent_companion_oauth_dcr',
		'wp_agent_companion_oauth_device_rate',
		'wp_agent_site_context',
		'wp_agent_design_profile',
		'wp_agent_design_directions',
		'wp_agent_active_design_direction',
		'wp_agent_design_directions_lock',
		'wp_agent_state_lock',
		'wp_agent_content_replace_operations',
		'wp_agent_content_replace_lock',
		'wp_agent_global_styles_lock',
		'wp_agent_spectra_one_snapshot_lock',
		'wp_agent_rank_math_redirection_lock',
		'wp_agent_seo_settings_lock',
		'wp_agent_seopress_redirection_graph_lock',
		'wp_agent_astra_settings_lock',
		'wp_agent_generatepress_settings_lock',
		'wp_agent_kadence_settings_lock',
		'wp_agent_oceanwp_settings_lock',
		'wp_agent_ocean_extra_modules_lock',
		'wp_agent_ase_free_generator_lock',
		'wp_agent_wc_attribute_lock',
		'wp_agent_wc_shipping_class_lock',
		'wp_agent_switch_theme_lock',
		'wp_agent_weglot_settings_lock',
		'wpagent_beaver_templates_lock',
		'wpagent_beaver_global_settings_lock',
		'wp_agent_cptui_lock_post_type',
		'wp_agent_cptui_lock_taxonomy',
		'wp_agent_acpt_lock_content_model',
	);
	if ( $cleanup_preferences['skills'] ) {
		$site_options[] = 'wp_agent_saved_skills';
	}
	if ( $cleanup_preferences['memory'] ) {
		$site_options[] = 'wp_agent_memory';
	}
	foreach ( $site_options as $option ) {
		delete_option( $option );
	}
	if ( $cleanup_preferences['oauth'] ) {
		foreach ( array(
			'wp_agent_companion_oauth_clients',
			'wp_agent_companion_oauth_tokens',
			'wp_agent_companion_oauth_grants',
		) as $option ) {
			delete_option( $option );
		}
	}
	global $wpdb;
	$dynamic_prefixes = array(
		'wp_agent_browser_link_',
		'wp_agent_direct_media_upload_',
		'wp_agent_acf_group_lock_',
		'wp_agent_acf_model_lock_',
		'wp_agent_acf_value_lock_',
		'wp_agent_acpt_meta_lock_',
		'wp_agent_content_model_migration_lock_',
		'wp_agent_content_model_migration_result_',
		'wp_agent_acpt_product_data_lock_',
		'wp_agent_cf7_lock_',
		'wp_agent_elementor_lock_',
		'wp_agent_generatepress_post_lock_',
		'wp_agent_oceanwp_post_lock_',
		'wp_agent_fluent_fields_lock_',
		'wp_agent_fluent_delivery_lock_',
		'wp_agent_metabox_fields_lock_',
		'wp_agent_metabox_relationship_lock_',
		'wp_agent_metabox_settings_page_lock_',
		'wp_agent_pods_model_lock_',
		'wp_agent_pods_meta_values_lock_',
		'wp_agent_kadence_form_lock_',
		'wp_agent_cptui_lock_',
		'wp_agent_seo_lock_',
		'wp_agent_seopress_redirection_lock_',
		'wp_agent_site_editor_lock_',
		'wp_agent_live_editor_session_',
		'wp_agent_live_editor_user_',
		'wp_agent_live_editor_command_',
		'wp_agent_live_editor_lock_',
		'wp_agent_term_seo_lock_',
		'wp_agent_update_post_lock_',
		'wp_agent_wpforms_delivery_lock_',
		'wpagent_beaver_lock_',
		'wpagent_beaver_global_settings_revision_',
		'_transient_wpagently_chat_plan_',
		'_transient_timeout_wpagently_chat_plan_',
		'_transient_wpagently_chat_rate_',
		'_transient_timeout_wpagently_chat_rate_',
		'_transient_wpagent_oauth_dcr_',
		'_transient_timeout_wpagent_oauth_dcr_',
		'_transient_wpagent_license_notice_',
		'_transient_timeout_wpagent_license_notice_',
		'wpagently_chat_lock_',
	);
	foreach ( $dynamic_prefixes as $prefix ) {
		$dynamic_options = $wpdb->get_col(
			$wpdb->prepare(
				"SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE %s",
				$wpdb->esc_like( $prefix ) . '%'
			)
		);
		foreach ( $dynamic_options as $dynamic_option ) {
			delete_option( $dynamic_option );
		}
	}
	wp_clear_scheduled_hook( 'wpagent_companion_license_daily_check' );
};

if ( is_multisite() && function_exists( 'get_sites' ) ) {
	$offset = 0;
	do {
		$site_ids = get_sites( array( 'fields' => 'ids', 'number' => 100, 'offset' => $offset ) );
		foreach ( $site_ids as $site_id ) {
			switch_to_blog( (int) $site_id );
			$cleanup_site();
			restore_current_blog();
		}
		$offset += count( $site_ids );
	} while ( count( $site_ids ) === 100 );
} else {
	$cleanup_site();
}

delete_site_transient( 'wpagent_update_' . md5( 'https://www.wpagently.com/updates/wp-agent-companion.json' ) );
