<?php
/**
 * KooKoa Folders — Uninstall cleanup.
 *
 * Runs once when the user chooses "Delete" in the Plugins screen
 * (not on deactivate). Respects the "Keep folders and settings when
 * the plugin is deleted" setting from tab General.
 *
 * Implementation notes:
 *  - The plugin's custom taxonomies are not registered in the uninstall
 *    context, so we re-register them here (for every post type WP knows
 *    about) before calling wp_delete_term(). This lets us stay on the
 *    native WordPress APIs throughout — no raw $wpdb queries needed.
 *  - Option / user meta / transient keys are enumerated explicitly so
 *    cleanup is auditable and limited to keys this plugin actually owns.
 *    The list includes legacy keys from older releases so users updating
 *    from pre-1.0 installs end up with a clean database.
 *  - The hierarchical-taxonomy children cache ({taxonomy}_children) is
 *    auto-created by WP whenever the tree is queried, so it is wiped per
 *    taxonomy alongside the term deletion loop.
 *  - Edge case: a post type provided by a plugin that has been deactivated
 *    before uninstall will leave its kookoawpf_folder_{cpt} taxonomy
 *    orphaned. Re-activating the source plugin and reinstalling KooKoa
 *    Folders cleans them up via the upgrade path.
 *
 * @package KookoaWPF
 */

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

// Honor the user's choice: keep data if opted in.
if ( 'yes' === get_option( 'kookoawpf_keep_data_on_uninstall', 'no' ) ) {
	return;
}

/*
 * 1. Folder taxonomies — register on the fly so wp_delete_term() works.
 *    Cover both the post types the user explicitly enabled and every WP
 *    post type currently registered (attachment, post, page, plus any CPT
 *    from plugins still active at uninstall time).
 */
$kookoawpf_enabled_pts = (array) get_option( 'kookoawpf_enabled_post_types', array( 'attachment' ) );
$kookoawpf_runtime_pts = get_post_types( array(), 'names' );
$kookoawpf_all_pts     = array_unique( array_merge( $kookoawpf_enabled_pts, (array) $kookoawpf_runtime_pts ) );
$kookoawpf_taxonomies  = array();

foreach ( $kookoawpf_all_pts as $kookoawpf_pt ) {
	$kookoawpf_pt = sanitize_key( (string) $kookoawpf_pt );
	if ( '' === $kookoawpf_pt ) {
		continue;
	}
	$kookoawpf_tax = 'kookoawpf_folder_' . $kookoawpf_pt;
	if ( ! taxonomy_exists( $kookoawpf_tax ) ) {
		register_taxonomy(
			$kookoawpf_tax,
			$kookoawpf_pt,
			array(
				'public'       => false,
				'hierarchical' => true,
				'rewrite'      => false,
				'query_var'    => false,
				'show_in_rest' => false,
			)
		);
	}
	$kookoawpf_taxonomies[] = $kookoawpf_tax;
}

foreach ( $kookoawpf_taxonomies as $kookoawpf_tax ) {
	$kookoawpf_term_ids = get_terms(
		array(
			'taxonomy'   => $kookoawpf_tax,
			'hide_empty' => false,
			'fields'     => 'ids',
		)
	);
	if ( is_wp_error( $kookoawpf_term_ids ) ) {
		continue;
	}
	foreach ( (array) $kookoawpf_term_ids as $kookoawpf_term_id ) {
		wp_delete_term( (int) $kookoawpf_term_id, $kookoawpf_tax );
	}
	// WP auto-creates a "{taxonomy}_children" option to cache the term hierarchy
	// whenever a hierarchical taxonomy is queried. Wipe it explicitly.
	delete_option( $kookoawpf_tax . '_children' );
}

// 2. Postmeta keys owned by this plugin.
delete_post_meta_by_key( '_kookoawpf_cleanup_trash' );

// 3. Plugin options (explicit allowlist — auditable, no LIKE scans).
$kookoawpf_options = array(
	// Currently used by 1.0.x / 1.1.x.
	'kookoawpf_allowed_roles',
	'kookoawpf_breadcrumb_style',
	'kookoawpf_ctx_disabled',
	'kookoawpf_custom_colors',
	'kookoawpf_db_version',
	'kookoawpf_enabled_post_types',
	'kookoawpf_folder_color',
	'kookoawpf_force_english',
	'kookoawpf_icon_blocks_disabled',
	'kookoawpf_install_time',
	'kookoawpf_keep_data_on_uninstall',
	'kookoawpf_migrate_section_hidden_forever',
	'kookoawpf_shortcuts_enabled',
	'kookoawpf_show_breadcrumb',
	'kookoawpf_show_exif',
	'kookoawpf_show_folder_stats',
	'kookoawpf_show_item_count',
	'kookoawpf_show_metadata_tooltip',
	'kookoawpf_show_subfolder_cards',
	'kookoawpf_sidebar_width',
	'kookoawpf_sticky_sidebar',
	'kookoawpf_tree_font_size',
	'kookoawpf_trial_used',
	'kookoawpf_trial_block3_locked',
	'kookoawpf_dynamic_term_ids',
	// FASE 4 commercial-UI lifecycle flags. Set-only by design (the
	// product never re-enables an upsell on a confirmed customer), but
	// uninstall is the user's explicit opt-out of every plugin trace —
	// honour that and drop them too. Trial flags pair with the FASE 4
	// flag (commit 154 funnel notes) and follow the same policy here.
	'kookoawpf_paid_license_activated',
	'kookoawpf_trial_active',
	'kookoawpf_trial_ends',
	// Legacy keys from older releases — keep so updaters end up clean.
	'kookoawpf_default_folder',
	'kookoawpf_sort_folders_by',
);
foreach ( $kookoawpf_options as $kookoawpf_opt ) {
	delete_option( $kookoawpf_opt );
}

// 3a. Per-post-type dynamic options (sort preferences). The key is built
// from the enabled-post-types list captured above, so a CPT that lost its
// taxonomy registration still gets its option swept on uninstall.
foreach ( $kookoawpf_all_pts as $kookoawpf_pt ) {
	$kookoawpf_pt = sanitize_key( (string) $kookoawpf_pt );
	if ( '' === $kookoawpf_pt ) {
		continue;
	}
	delete_option( 'kookoawpf_sort_' . $kookoawpf_pt );
}

// 3b. Per-importer flags. Hardcoded ID list mirrors
// KookoaWPF_Importer_Registry::bootstrap() — the registry class is not
// loaded in the uninstall context, so we cannot iterate it dynamically.
// If a new importer is added, its ID must be appended here too.
$kookoawpf_importer_ids = array(
	'filebird-media',
	'filebird-post',
	'filebird-page',
	'premio-folders-media',
	'premio-folders-post',
	'premio-folders-page',
	'rml-media',
);
foreach ( $kookoawpf_importer_ids as $kookoawpf_importer_id ) {
	$kookoawpf_suffix = str_replace( '-', '_', $kookoawpf_importer_id );
	delete_option( 'kookoawpf_importer_imported_' . $kookoawpf_suffix );
	delete_option( 'kookoawpf_importer_dismissed_' . $kookoawpf_suffix );
	delete_option( 'kookoawpf_importer_lock_' . $kookoawpf_suffix );
}

// 4. Transients (kookoawpf_tree_dirty_{post_type} + smart-folder caches).
foreach ( $kookoawpf_all_pts as $kookoawpf_pt ) {
	$kookoawpf_pt = sanitize_key( (string) $kookoawpf_pt );
	if ( '' === $kookoawpf_pt ) {
		continue;
	}
	delete_transient( 'kookoawpf_tree_dirty_' . $kookoawpf_pt );

	// Smart-folder count + matching-IDs caches: walk every term in the
	// taxonomy and drop the canonical transient keys. Skips silently when
	// the taxonomy was never registered for this post type.
	$kookoawpf_tax = 'kookoawpf_folder_' . $kookoawpf_pt;
	if ( ! taxonomy_exists( $kookoawpf_tax ) ) {
		continue;
	}
	$kookoawpf_term_ids = get_terms(
		array(
			'taxonomy'   => $kookoawpf_tax,
			'hide_empty' => false,
			'fields'     => 'ids',
		)
	);
	if ( is_wp_error( $kookoawpf_term_ids ) ) {
		continue;
	}
	foreach ( $kookoawpf_term_ids as $kookoawpf_tid ) {
		delete_transient( 'kookoawpf_dyn_count_' . (int) $kookoawpf_tid . '_' . $kookoawpf_pt );
		delete_transient( 'kookoawpf_dyn_ids_' . (int) $kookoawpf_tid . '_' . $kookoawpf_pt );
	}
}

// 4a. Temp download workspace created by the ZIP download feature
// (uploads/kookoawpf-tmp/ + its throttle transient). Per-download subdirs are
// normally cron-cleaned, but the root directory and its index.php/.htaccess
// infrastructure files persist, so remove the whole tree on uninstall.
delete_transient( 'kookoawpf_tmp_zip_last_prune' );
$kookoawpf_upload = wp_upload_dir();
if ( empty( $kookoawpf_upload['error'] ) && ! empty( $kookoawpf_upload['basedir'] ) ) {
	$kookoawpf_tmp_dir = trailingslashit( $kookoawpf_upload['basedir'] ) . 'kookoawpf-tmp';
	if ( is_dir( $kookoawpf_tmp_dir ) ) {
		if ( ! function_exists( 'WP_Filesystem' ) ) {
			require_once ABSPATH . 'wp-admin/includes/file.php';
		}
		WP_Filesystem();
		global $wp_filesystem;
		if ( $wp_filesystem && $wp_filesystem->is_dir( $kookoawpf_tmp_dir ) ) {
			$wp_filesystem->delete( $kookoawpf_tmp_dir, true );
		}
	}
}

// 5. Per-user meta (per-user preferences + per-user dismiss flags).
// delete_metadata( ..., 0, $key, '', true ) deletes the meta_key across
// every user in one call — far cheaper than enumerating users.
$kookoawpf_user_meta_keys = array(
	// Smart Startup Folder preferences.
	'kookoawpf_startup_mode',
	'kookoawpf_startup_folder_ids',
	// Per-user drag-resize override of the site-wide sidebar width.
	'kookoawpf_sidebar_width',
	// Per-user dismiss flags for dashboard / settings notices.
	'kookoawpf_notice_trial_invite_dismissed',
	'kookoawpf_notice_trial_discount_dismissed',
	'kookoawpf_notice_review_dashboard_dismissed',
	'kookoawpf_review_dismissed',
	'kookoawpf_review_clicked',
	'kookoawpf_sidebar_migrate_hint_dismissed',
);
foreach ( $kookoawpf_user_meta_keys as $kookoawpf_umk ) {
	delete_metadata( 'user', 0, $kookoawpf_umk, '', true );
}
// Per-post-type "last opened folder" user meta — one key per pt.
foreach ( $kookoawpf_all_pts as $kookoawpf_pt ) {
	$kookoawpf_pt = sanitize_key( (string) $kookoawpf_pt );
	if ( '' === $kookoawpf_pt ) {
		continue;
	}
	delete_metadata( 'user', 0, 'kookoawpf_last_folder_' . $kookoawpf_pt, '', true );
}

wp_cache_flush();
