<?php
/**
 * Uninstall — runs only when the user clicks "Delete" on the Plugins screen.
 *
 * SAFE-LIFECYCLE POLICY (non-negotiable, learned the hard way):
 *   A plain "Delete" must NEVER destroy user data, settings, custom roles, or
 *   role assignments as a side effect. During development a plugin is
 *   frequently deactivated, deleted, re-uploaded and re-activated — WordPress
 *   fires this file on every delete. A previous internal plugin stripped a
 *   real user's role on every redeploy because of careless uninstall logic.
 *   Never again.
 *
 * DEFAULT BEHAVIOUR: preserve everything. The only thing cleared on a plain
 * delete is ephemeral, self-regenerating job transients, which hold no
 * configuration and are safe to drop.
 *
 * OPT-IN TEARDOWN: a full removal of settings and data happens ONLY when the
 * site owner has explicitly enabled "Remove all data on uninstall" in
 * Platform Helm → Modules → Data & Privacy. That flag lives inside the single
 * settings option, so we read it before deciding to do anything destructive.
 *
 * @package Platform\Helm
 */

declare( strict_types = 1 );

// Hard guard — only ever run via WordPress's uninstall mechanism.
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
	exit;
}

global $wpdb;

$option_key = 'platform_helm_settings';

/*
 * Always-safe cleanup: clear ephemeral job transients. These regenerate on
 * demand and contain no configuration, so dropping them just means a fresh
 * install starts with no stale locks or job state.
 */
$transient_prefixes = [
	'_transient_platform_helm_ls_',     // Link Suggester ephemeral state.
	'_transient_platform_helm_la_job_', // Link Architect job state.
	'_transient_platform_helm_lk_',     // Link Architect job/approval state.
	'_transient_platform_helm_pulse_',  // Dashboard pulse cache.
	'_transient_platform_helm_health_', // Link Health report cache.
	'_transient_platform_helm_pd_',     // Persona Dashboards data cache.
];
foreach ( $transient_prefixes as $prefix ) {
	$like = $wpdb->esc_like( $prefix ) . '%';
	$keys = $wpdb->get_col( $wpdb->prepare(
		"SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE %s",
		$like
	) );
	foreach ( (array) $keys as $name ) {
		$transient_name = preg_replace( '/^_transient_/', '', (string) $name );
		if ( $transient_name ) {
			delete_transient( $transient_name );
		}
	}
}

/*
 * Destructive teardown — ONLY if the owner explicitly opted in. We read the
 * preference straight from the stored option (the plugin's classes are not
 * loaded during uninstall, so we use get_option directly).
 */
$settings    = get_option( $option_key, [] );
$remove_data = is_array( $settings ) && ! empty( $settings['remove_data_on_uninstall'] );

if ( ! $remove_data ) {
	/*
	 * Preserve-by-default path. Intentionally kept:
	 *   - platform_helm_settings (module enablement + preferences)
	 *   - any module data (link backups, etc.)
	 * Nothing further to do.
	 */
	return;
}

/*
 * Opt-in full teardown. Remove the single settings option. Module-specific
 * data cleanup (e.g. link-insertion backups) will be added here as those
 * modules ship, each guarded by the same opt-in flag. Roles and role
 * assignments are never touched here regardless of this flag — role teardown,
 * if ever needed, must be a deliberate, separate, documented action.
 */
delete_option( $option_key );

/*
 * Module-owned data, removed only under the same opt-in flag:
 *   - Activity Log custom table + its schema option.
 *   - Link Suggester settings, Role Manager menu map, Persona schema option.
 * Roles and role assignments are never touched here regardless of this flag.
 */
$activity_table = $wpdb->prefix . 'platform_helm_activity';
// phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.SchemaChange
$wpdb->query( "DROP TABLE IF EXISTS {$activity_table}" );

// Search Console + Content Auditor custom tables (Phase 6).
$helm_tables = [
	$wpdb->prefix . 'platform_helm_gsc',
	$wpdb->prefix . 'platform_helm_gsc_queries',
	$wpdb->prefix . 'platform_helm_gsc_snapshots',
	$wpdb->prefix . 'platform_helm_gsc_index',
	$wpdb->prefix . 'platform_helm_audit',
];
foreach ( $helm_tables as $helm_table ) {
	// phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.SchemaChange
	$wpdb->query( "DROP TABLE IF EXISTS {$helm_table}" );
}

delete_option( 'platform_helm_activity_schema' );
delete_option( 'platform_helm_link_suggester' );
delete_option( 'platform_helm_role_menu_hidden' );
delete_option( 'platform_helm_health_snapshot' );
delete_option( 'platform_helm_health_alert' );
delete_option( 'platform_helm_setup_complete' );
delete_option( 'platform_helm_do_setup_redirect' );

// Phase 4–6 module options (AI, GSC, Content Auditor). Removed only under
// the same opt-in flag.
$helm_options = [
	'platform_helm_llm',
	'platform_helm_ai_last_brief',
	'platform_helm_gsc_credentials',
	'platform_helm_gsc_auth_method',
	'platform_helm_gsc_oauth',
	'platform_helm_gsc_property',
	'platform_helm_gsc_range_days',
	'platform_helm_gsc_last_sync',
	'platform_helm_gsc_watchlist',
	'platform_helm_gsc_schema_version',
	'platform_helm_gsc_q_schema_version',
	'platform_helm_gsc_snap_schema_version',
	'platform_helm_gsc_index_schema_version',
	'platform_helm_offbrand_terms',
	'platform_helm_audit_schema_version',
	'platform_helm_audit_brief',
	'platform_helm_login_branding',
];
foreach ( $helm_options as $helm_option ) {
	delete_option( $helm_option );
}

// Link Architect "built links" memory, stored as post meta on source posts.
// Bounded single query; only runs under explicit opt-in teardown.
// phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->query( $wpdb->prepare(
	"DELETE FROM {$wpdb->postmeta} WHERE meta_key = %s",
	'_platform_helm_built_links'
) );

// Dismissed-suggestion memory (Link Suggester), also post meta.
// phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->query( $wpdb->prepare(
	"DELETE FROM {$wpdb->postmeta} WHERE meta_key = %s",
	'_platform_helm_dismissed_links'
) );

// Link Assassin per-post backups (timestamped meta keys share a prefix).
// phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->query( $wpdb->prepare(
	"DELETE FROM {$wpdb->postmeta} WHERE meta_key LIKE %s",
	$wpdb->esc_like( '_platform_helm_la_backup_' ) . '%'
) );

// Schema editor per-post structured data.
// phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->query( $wpdb->prepare(
	"DELETE FROM {$wpdb->postmeta} WHERE meta_key IN ( %s, %s )",
	'_platform_helm_schema_howto',
	'_platform_helm_schema_faq'
) );

// Ghost Purge last-login tracking (user meta).
// phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->query( $wpdb->prepare(
	"DELETE FROM {$wpdb->usermeta} WHERE meta_key = %s",
	'_platform_helm_last_login'
) );
