<?php
/**
 * Admin Data Export/Import Class
 *
 * Handles the data export and import functionality in the WordPress admin.
 * Provides backup, migration, and data import capabilities.
 *
 * @package    Karate_Club_Manager
 * @subpackage Karate_Club_Manager/includes/admin
 * @since      1.0.265
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * MACM Admin Data Class
 *
 * Manages data export and import operations.
 *
 * @since 1.0.265
 */
class MACM_Admin_Data {

	/**
	 * Initialize the class and set up hooks.
	 *
	 * @since 1.0.265
	 */
	public function __construct() {
		add_action( 'admin_menu', array( $this, 'register_menu_page' ), 21 );
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );

		// Register form handlers for export/import.
		add_action( 'admin_post_macm_export_data', array( $this, 'handle_export' ) );
		add_action( 'admin_post_macm_import_data', array( $this, 'handle_import' ) );

		// Register AJAX handlers for import validation and reset.
		add_action( 'wp_ajax_macm_validate_import', array( $this, 'ajax_validate_import' ) );
		add_action( 'wp_ajax_macm_process_import', array( $this, 'ajax_process_import' ) );
		add_action( 'wp_ajax_macm_reset_plugin_data', array( $this, 'ajax_reset_plugin_data' ) );
	}

	/**
	 * Register the Data submenu page.
	 *
	 * @since 1.0.265
	 */
	public function register_menu_page() {
		add_submenu_page(
			'martial-arts-club-manager',
			__( 'Export/Import', 'martial-arts-club-manager' ),
			__( 'Export/Import', 'martial-arts-club-manager' ),
			'manage_options',
			'macm-data',
			array( $this, 'display_page' ),
			21
		);
	}

	/**
	 * Enqueue admin scripts and styles.
	 *
	 * @since 1.0.265
	 * @param string $hook The current admin page hook.
	 */
	public function enqueue_scripts( $hook ) {
		// Only load on our data page.
		if ( 'martial-arts_page_macm-data' !== $hook ) {
			return;
		}

		// Enqueue custom admin data styles.
		wp_enqueue_style(
			'macm-admin-data',
			MACM_PLUGIN_URL . 'assets/css/admin-data.css',
			array(),
			MACM_VERSION . '.' . filemtime( MACM_PLUGIN_DIR . 'assets/css/admin-data.css' )
		);

		// Enqueue custom admin data scripts.
		wp_enqueue_script(
			'macm-admin-data',
			MACM_PLUGIN_URL . 'assets/js/admin-data.js',
			array( 'jquery' ),
			MACM_VERSION,
			true
		);

		// Localize script for AJAX and translations.
		wp_localize_script(
			'macm-admin-data',
			'macmDataAdmin',
			array(
				'ajaxUrl' => admin_url( 'admin-ajax.php' ),
				'nonce'   => wp_create_nonce( 'macm_data_nonce' ),
				'i18n'    => array(
					'selectFile'      => __( 'Please select a file to import.', 'martial-arts-club-manager' ),
					'selectDataType'  => __( 'Please select at least one data type to export.', 'martial-arts-club-manager' ),
					'invalidFileType' => __( 'Invalid file type. Please select a JSON or CSV file.', 'martial-arts-club-manager' ),
					'fileTooLarge'    => __( 'File is too large. Maximum size is 10MB.', 'martial-arts-club-manager' ),
					'confirmImport'   => __( 'Are you sure you want to import this data? This action cannot be undone.', 'martial-arts-club-manager' ),
					'importing'       => __( 'Importing...', 'martial-arts-club-manager' ),
					'exportSuccess'   => __( 'Export completed successfully.', 'martial-arts-club-manager' ),
					'importSuccess'   => __( 'Import completed successfully.', 'martial-arts-club-manager' ),
					'error'           => __( 'An error occurred. Please try again.', 'martial-arts-club-manager' ),
					'resetConfirm1'   => __( 'WARNING: You are about to permanently delete ALL plugin data!', 'martial-arts-club-manager' ),
					'resetConfirm2'   => __( 'This includes all members, classes, attendance records, events, and settings.', 'martial-arts-club-manager' ),
					'resetConfirm3'   => __( 'Type "RESET" to confirm:', 'martial-arts-club-manager' ),
					'resetCancelled'  => __( 'Reset cancelled. No data was deleted.', 'martial-arts-club-manager' ),
					'resetting'       => __( 'Resetting...', 'martial-arts-club-manager' ),
					'resetSuccess'    => __( 'All plugin data has been reset successfully.', 'martial-arts-club-manager' ),
				),
			)
		);
	}

	/**
	 * Display the data export/import page.
	 *
	 * @since 1.0.265
	 */
	public function display_page() {
		// Check user capabilities.
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'martial-arts-club-manager' ) );
		}

		// Build available tabs.
		$tabs = array(
			'export' => __( 'Export', 'martial-arts-club-manager' ),
			'import' => __( 'Import', 'martial-arts-club-manager' ),
			'reset'  => __( 'Reset', 'martial-arts-club-manager' ),
		);

		// Get current tab.
		$current_tab = $this->get_current_tab( array_keys( $tabs ) );

		// Get exportable entities.
		$entities = $this->get_exportable_entities();

		// Load the data page template.
		include MACM_PLUGIN_DIR . 'templates/admin/data-page.php';
	}

	/**
	 * Get current tab from request.
	 *
	 * @since 1.0.265
	 * @param array $allowed_tabs Array of allowed tab slugs.
	 * @return string The validated current tab slug.
	 */
	private function get_current_tab( $allowed_tabs ) {
		$tab_input = filter_input( INPUT_GET, 'tab', FILTER_SANITIZE_FULL_SPECIAL_CHARS );

		if ( empty( $tab_input ) ) {
			return 'export';
		}

		if ( in_array( $tab_input, $allowed_tabs, true ) ) {
			return $tab_input;
		}

		return 'export';
	}

	/**
	 * Get list of exportable entities.
	 *
	 * Returns an array of entities that can be exported, with premium gating.
	 * Uses transient caching to avoid rebuilding the array on each page load.
	 *
	 * @since 1.0.265
	 * @return array Array of entity definitions.
	 */
	public function get_exportable_entities() {
		// Check transient cache first.
		$cache_key = 'macm_exportable_entities';
		$entities  = get_transient( $cache_key );

		if ( false !== $entities ) {
			return $entities;
		}

		// Build entities array.
		$can_use_premium = function_exists( 'macm_fs' ) && macm_fs()->can_use_premium_code();

		$entities = array(
			'free'    => array(
				'label'    => __( 'Free Features', 'martial-arts-club-manager' ),
				'entities' => array(
					'settings'         => array(
						'label'       => __( 'Plugin Settings', 'martial-arts-club-manager' ),
						'description' => __( 'General settings, button colors, WooCommerce settings', 'martial-arts-club-manager' ),
						'premium'     => false,
					),
					'belt_colors'      => array(
						'label'       => __( 'Belt Colors', 'martial-arts-club-manager' ),
						'description' => __( 'Belt color definitions and order', 'martial-arts-club-manager' ),
						'premium'     => false,
					),
					'membership_types' => array(
						'label'       => __( 'Membership Types', 'martial-arts-club-manager' ),
						'description' => __( 'Membership type definitions', 'martial-arts-club-manager' ),
						'premium'     => false,
					),
					'members'          => array(
						'label'       => __( 'Members', 'martial-arts-club-manager' ),
						'description' => __( 'Member profiles (linked to users by email)', 'martial-arts-club-manager' ),
						'premium'     => false,
					),
					'trial_bookings'   => array(
						'label'       => __( 'Trial Bookings', 'martial-arts-club-manager' ),
						'description' => __( 'Trial class booking requests', 'martial-arts-club-manager' ),
						'premium'     => false,
					),
				),
			),
			'premium' => array(
				'label'    => __( 'Premium Features', 'martial-arts-club-manager' ),
				'entities' => array(
					'locations'           => array(
						'label'       => __( 'Locations', 'martial-arts-club-manager' ),
						'description' => __( 'Training locations/dojos', 'martial-arts-club-manager' ),
						'premium'     => true,
						'available'   => $can_use_premium,
					),
					'groups'              => array(
						'label'       => __( 'Groups', 'martial-arts-club-manager' ),
						'description' => __( 'Member groups and assignments', 'martial-arts-club-manager' ),
						'premium'     => true,
						'available'   => $can_use_premium,
					),
					'clubs'               => array(
						'label'       => __( 'Clubs', 'martial-arts-club-manager' ),
						'description' => __( 'Club/dojo organizations', 'martial-arts-club-manager' ),
						'premium'     => true,
						'available'   => $can_use_premium,
					),
					'instructors'         => array(
						'label'       => __( 'Instructors', 'martial-arts-club-manager' ),
						'description' => __( 'Instructor profiles', 'martial-arts-club-manager' ),
						'premium'     => true,
						'available'   => $can_use_premium,
					),
					'classes'             => array(
						'label'       => __( 'Classes', 'martial-arts-club-manager' ),
						'description' => __( 'Class schedules and configurations', 'martial-arts-club-manager' ),
						'premium'     => true,
						'available'   => $can_use_premium,
					),
					'class_enrollments'   => array(
						'label'       => __( 'Class Enrollments', 'martial-arts-club-manager' ),
						'description' => __( 'Member-class enrollment records', 'martial-arts-club-manager' ),
						'premium'     => true,
						'available'   => $can_use_premium,
					),
					'attendance'          => array(
						'label'       => __( 'Attendance Records', 'martial-arts-club-manager' ),
						'description' => __( 'Class attendance history', 'martial-arts-club-manager' ),
						'premium'     => true,
						'available'   => $can_use_premium,
					),
					'events'              => array(
						'label'       => __( 'Events', 'martial-arts-club-manager' ),
						'description' => __( 'Tournaments, seminars, and events', 'martial-arts-club-manager' ),
						'premium'     => true,
						'available'   => $can_use_premium,
					),
					'event_registrations' => array(
						'label'       => __( 'Event Registrations', 'martial-arts-club-manager' ),
						'description' => __( 'Event registration records', 'martial-arts-club-manager' ),
						'premium'     => true,
						'available'   => $can_use_premium,
					),
					'training_videos'     => array(
						'label'       => __( 'Training Videos', 'martial-arts-club-manager' ),
						'description' => __( 'Video library entries', 'martial-arts-club-manager' ),
						'premium'     => true,
						'available'   => $can_use_premium,
					),
					'grading_history'     => array(
						'label'       => __( 'Grading History', 'martial-arts-club-manager' ),
						'description' => __( 'Belt grading records', 'martial-arts-club-manager' ),
						'premium'     => true,
						'available'   => $can_use_premium,
					),
				),
			),
		);

		/**
		 * Filter the exportable entities list.
		 *
		 * @since 1.0.265
		 * @param array $entities Array of entity definitions.
		 */
		$entities = apply_filters( 'macm_exportable_entities', $entities );

		// Cache for 1 hour.
		set_transient( $cache_key, $entities, HOUR_IN_SECONDS );

		return $entities;
	}

	/**
	 * Handle export data form submission.
	 *
	 * Processes the export form, validates inputs, and generates the export file.
	 *
	 * @since 1.0.265
	 * @since 1.0.268 Implemented export logic.
	 */
	public function handle_export() {
		// Verify nonce.
		if ( ! isset( $_POST['macm_export_nonce'] ) ) {
			wp_die( esc_html__( 'Security check failed.', 'martial-arts-club-manager' ) );
		}

		$nonce = sanitize_text_field( wp_unslash( $_POST['macm_export_nonce'] ) );

		if ( ! wp_verify_nonce( $nonce, 'macm_export_data' ) ) {
			wp_die( esc_html__( 'Security check failed.', 'martial-arts-club-manager' ) );
		}

		// Check user capabilities.
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have permission to export data.', 'martial-arts-club-manager' ) );
		}

		// Get selected entities.
		$entities = array();
		if ( isset( $_POST['export_entities'] ) && is_array( $_POST['export_entities'] ) ) {
			$raw_entities = array_map( 'sanitize_key', $_POST['export_entities'] );

			// Validate against allowed entity keys.
			$allowed_entities = $this->get_allowed_entity_keys();
			$entities         = array_intersect( $raw_entities, $allowed_entities );
		}

		if ( empty( $entities ) ) {
			wp_die( esc_html__( 'Please select at least one valid data type to export.', 'martial-arts-club-manager' ) );
		}

		// Get export format.
		$format = 'json';
		if ( isset( $_POST['export_format'] ) ) {
			$format = sanitize_key( $_POST['export_format'] );
		}

		if ( ! in_array( $format, array( 'json', 'csv' ), true ) ) {
			$format = 'json';
		}

		// Create exporter instance.
		$exporter = new MACM_Data_Export();

		// Generate filename parts.
		$site_name = sanitize_title( get_bloginfo( 'name' ) );
		$timestamp = gmdate( 'Y-m-d-His' );

		if ( 'json' === $format ) {
			// JSON exports all entities in one file.
			$export_data = $exporter->export_entities( $entities, $format );

			if ( is_wp_error( $export_data ) ) {
				wp_die( esc_html( $export_data->get_error_message() ) );
			}

			$this->output_json_export( $export_data, $site_name, $timestamp );
		} elseif ( count( $entities ) > 1 ) {
			// Multiple entities with CSV format - create ZIP with multiple CSVs.
			$this->output_csv_zip_export( $exporter, $entities, $site_name, $timestamp );
		} else {
			// Single entity CSV export.
			$export_data = $exporter->export_entities( $entities, $format );

			if ( is_wp_error( $export_data ) ) {
				wp_die( esc_html( $export_data->get_error_message() ) );
			}

			$this->output_csv_export( $export_data, $site_name, $timestamp );
		}

		exit;
	}

	/**
	 * Get list of allowed entity keys for export validation.
	 *
	 * @since 1.0.268
	 * @return array Array of allowed entity key strings.
	 */
	private function get_allowed_entity_keys() {
		$exportable = $this->get_exportable_entities();
		$keys       = array();

		foreach ( $exportable as $group ) {
			if ( isset( $group['entities'] ) && is_array( $group['entities'] ) ) {
				$keys = array_merge( $keys, array_keys( $group['entities'] ) );
			}
		}

		return $keys;
	}

	/**
	 * Sanitize filename for Content-Disposition header.
	 *
	 * @since 1.0.268
	 * @param string $filename Raw filename.
	 * @return string Safe filename with only alphanumeric, dash, underscore, dot.
	 */
	private function sanitize_export_filename( $filename ) {
		return preg_replace( '/[^a-zA-Z0-9_\-\.]/', '', $filename );
	}

	/**
	 * Output JSON export file.
	 *
	 * @since 1.0.268
	 * @param array  $data      Export data array.
	 * @param string $site_name Sanitized site name for filename.
	 * @param string $timestamp Timestamp for filename.
	 */
	private function output_json_export( $data, $site_name, $timestamp ) {
		$filename = sprintf( 'macm-export-%s-%s.json', $site_name, $timestamp );
		$filename = $this->sanitize_export_filename( $filename );

		// Clean output buffer.
		if ( ob_get_level() ) {
			ob_end_clean();
		}

		// Set headers for file download.
		header( 'Content-Type: application/json; charset=utf-8' );
		header( 'Content-Disposition: attachment; filename="' . $filename . '"' );
		header( 'Cache-Control: no-cache, no-store, must-revalidate' );
		header( 'Pragma: no-cache' );
		header( 'Expires: 0' );

		// Output JSON with pretty print for readability.
		// phpcs:ignore WordPress.WP.AlternativeFunctions.json_encode_json_encode
		echo wp_json_encode( $data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE );
	}

	/**
	 * Output CSV export file.
	 *
	 * @since 1.0.268
	 * @param array  $data      Export data array with 'headers', 'rows', 'entity'.
	 * @param string $site_name Sanitized site name for filename.
	 * @param string $timestamp Timestamp for filename.
	 */
	private function output_csv_export( $data, $site_name, $timestamp ) {
		$entity   = isset( $data['entity'] ) ? sanitize_key( $data['entity'] ) : 'data';
		$filename = sprintf( 'macm-%s-%s-%s.csv', $entity, $site_name, $timestamp );
		$filename = $this->sanitize_export_filename( $filename );

		// Clean output buffer.
		if ( ob_get_level() ) {
			ob_end_clean();
		}

		// Set headers for file download.
		header( 'Content-Type: text/csv; charset=utf-8' );
		header( 'Content-Disposition: attachment; filename="' . $filename . '"' );
		header( 'Cache-Control: no-cache, no-store, must-revalidate' );
		header( 'Pragma: no-cache' );
		header( 'Expires: 0' );

		// Open output stream.
		// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen
		$output = fopen( 'php://output', 'w' );

		if ( false === $output ) {
			wp_die( esc_html__( 'Failed to create export stream.', 'martial-arts-club-manager' ) );
		}

		// Add UTF-8 BOM for Excel compatibility.
		// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fwrite
		fwrite( $output, chr( 0xEF ) . chr( 0xBB ) . chr( 0xBF ) );

		// Write headers.
		if ( ! empty( $data['headers'] ) ) {
			fputcsv( $output, $data['headers'] );
		}

		// Write rows.
		if ( ! empty( $data['rows'] ) ) {
			foreach ( $data['rows'] as $row ) {
				fputcsv( $output, $row );
			}
		}

		// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose
		fclose( $output );
	}

	/**
	 * Output multiple CSV files as a ZIP archive.
	 *
	 * Creates a ZIP file containing one CSV file per selected entity.
	 *
	 * @since 1.0.282
	 * @param MACM_Data_Export $exporter  Exporter instance.
	 * @param array            $entities  Array of entity keys to export.
	 * @param string           $site_name Sanitized site name for filename.
	 * @param string           $timestamp Timestamp for filename.
	 */
	private function output_csv_zip_export( $exporter, $entities, $site_name, $timestamp ) {
		// Check if ZipArchive is available.
		if ( ! class_exists( 'ZipArchive' ) ) {
			wp_die( esc_html__( 'ZIP extension is not available. Please export entities one at a time or use JSON format.', 'martial-arts-club-manager' ) );
		}

		// Create temp file for ZIP.
		$upload_dir = wp_upload_dir();
		$temp_dir   = $upload_dir['basedir'] . '/macm-temp';

		// Create temp directory if it doesn't exist.
		if ( ! file_exists( $temp_dir ) ) {
			wp_mkdir_p( $temp_dir );
		}

		$zip_filename = sprintf( 'macm-export-%s-%s.zip', $site_name, $timestamp );
		$zip_filepath = $temp_dir . '/' . $zip_filename;

		// Create ZIP archive.
		$zip    = new ZipArchive();
		$result = $zip->open( $zip_filepath, ZipArchive::CREATE | ZipArchive::OVERWRITE );

		if ( true !== $result ) {
			wp_die( esc_html__( 'Failed to create ZIP archive.', 'martial-arts-club-manager' ) );
		}

		// Export each entity as CSV and add to ZIP.
		foreach ( $entities as $entity ) {
			$csv_data = $exporter->export_to_csv( $entity );

			if ( is_wp_error( $csv_data ) ) {
				// Skip entities that fail to export (e.g., premium without license).
				continue;
			}

			// Generate CSV content.
			$csv_content = $this->generate_csv_content( $csv_data );

			if ( ! empty( $csv_content ) ) {
				$csv_filename = sprintf( 'macm-%s-%s-%s.csv', $entity, $site_name, $timestamp );
				$zip->addFromString( $csv_filename, $csv_content );
			}
		}

		$zip->close();

		// Check if ZIP has any files.
		if ( ! file_exists( $zip_filepath ) || filesize( $zip_filepath ) < 22 ) {
			// Empty ZIP or failed - cleanup and error.
			if ( file_exists( $zip_filepath ) ) {
				wp_delete_file( $zip_filepath );
			}
			wp_die( esc_html__( 'No data available to export for selected entities.', 'martial-arts-club-manager' ) );
		}

		// Clean output buffer.
		if ( ob_get_level() ) {
			ob_end_clean();
		}

		// Set headers for ZIP download.
		header( 'Content-Type: application/zip' );
		header( 'Content-Disposition: attachment; filename="' . $zip_filename . '"' );
		header( 'Content-Length: ' . filesize( $zip_filepath ) );
		header( 'Cache-Control: no-cache, no-store, must-revalidate' );
		header( 'Pragma: no-cache' );
		header( 'Expires: 0' );

		// Output ZIP file.
		// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_readfile
		readfile( $zip_filepath );

		// Delete temp file.
		wp_delete_file( $zip_filepath );
	}

	/**
	 * Generate CSV content as a string.
	 *
	 * @since 1.0.282
	 * @param array $data CSV data with 'headers' and 'rows'.
	 * @return string CSV content with UTF-8 BOM.
	 */
	private function generate_csv_content( $data ) {
		if ( empty( $data['headers'] ) && empty( $data['rows'] ) ) {
			return '';
		}

		// Open memory stream.
		// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen
		$output = fopen( 'php://temp', 'w' );

		if ( false === $output ) {
			return '';
		}

		// Add UTF-8 BOM for Excel compatibility.
		// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fwrite
		fwrite( $output, chr( 0xEF ) . chr( 0xBB ) . chr( 0xBF ) );

		// Write headers.
		if ( ! empty( $data['headers'] ) ) {
			fputcsv( $output, $data['headers'] );
		}

		// Write rows.
		if ( ! empty( $data['rows'] ) ) {
			foreach ( $data['rows'] as $row ) {
				fputcsv( $output, $row );
			}
		}

		// Get content.
		rewind( $output );
		$content = stream_get_contents( $output );

		// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose
		fclose( $output );

		return $content;
	}

	/**
	 * Handle import data form submission.
	 *
	 * Processes the import form, validates the uploaded file, and imports data.
	 *
	 * @since 1.0.265
	 * @since 1.0.272 Implemented full import logic.
	 */
	public function handle_import() {
		// Verify nonce.
		if ( ! isset( $_POST['macm_import_nonce'] ) ) {
			wp_die( esc_html__( 'Security check failed.', 'martial-arts-club-manager' ) );
		}

		$nonce = sanitize_text_field( wp_unslash( $_POST['macm_import_nonce'] ) );

		if ( ! wp_verify_nonce( $nonce, 'macm_import_data' ) ) {
			wp_die( esc_html__( 'Security check failed.', 'martial-arts-club-manager' ) );
		}

		// Check user capabilities.
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have permission to import data.', 'martial-arts-club-manager' ) );
		}

		// Get import_id from the validated preview.
		if ( ! isset( $_POST['import_id'] ) || empty( $_POST['import_id'] ) ) {
			$this->redirect_with_error( __( 'Invalid import request. Please validate the file first.', 'martial-arts-club-manager' ) );
			return;
		}

		$import_id = sanitize_key( $_POST['import_id'] );
		$user_id   = get_current_user_id();

		// Retrieve import data from transient (includes user ID for security).
		$data = get_transient( 'macm_import_' . $user_id . '_' . $import_id );

		if ( false === $data ) {
			$this->redirect_with_error( __( 'Import session expired. Please upload the file again.', 'martial-arts-club-manager' ) );
			return;
		}

		// Get import options.
		$options = array(
			'user_mapping'        => isset( $_POST['user_mapping'] ) ? sanitize_key( $_POST['user_mapping'] ) : 'match_email',
			'conflict_resolution' => isset( $_POST['conflict_resolution'] ) ? sanitize_key( $_POST['conflict_resolution'] ) : 'skip',
		);

		// Validate options.
		$valid_user_mappings = array( 'match_email', 'assign_current', 'skip_unmatched' );
		if ( ! in_array( $options['user_mapping'], $valid_user_mappings, true ) ) {
			$options['user_mapping'] = 'match_email';
		}

		$valid_conflict_modes = array( 'skip', 'update', 'create' );
		if ( ! in_array( $options['conflict_resolution'], $valid_conflict_modes, true ) ) {
			$options['conflict_resolution'] = 'skip';
		}

		// Create importer and run import.
		$importer = new MACM_Data_Import();
		$results  = $importer->import( $data, $options );

		// Delete the transient after use.
		delete_transient( 'macm_import_' . $user_id . '_' . $import_id );

		if ( is_wp_error( $results ) ) {
			$this->redirect_with_error( $results->get_error_message() );
			return;
		}

		// Build success message.
		$total_imported = 0;
		$total_updated  = 0;
		$total_skipped  = 0;

		if ( isset( $results['entity_results'] ) ) {
			foreach ( $results['entity_results'] as $entity_result ) {
				$total_imported += $entity_result['imported'] ?? 0;
				$total_updated  += $entity_result['updated'] ?? 0;
				$total_skipped  += $entity_result['skipped'] ?? 0;
			}
		}

		$message = sprintf(
			/* translators: 1: number imported, 2: number updated, 3: number skipped */
			__( 'Import completed successfully. %1$d records imported, %2$d updated, %3$d skipped.', 'martial-arts-club-manager' ),
			$total_imported,
			$total_updated,
			$total_skipped
		);

		$this->redirect_with_success( $message );
	}

	/**
	 * Redirect to import page with error message.
	 *
	 * @since 1.0.272
	 * @param string $message Error message.
	 */
	private function redirect_with_error( $message ) {
		$redirect_url = add_query_arg(
			array(
				'page'         => 'macm-data',
				'tab'          => 'import',
				'import_error' => rawurlencode( $message ),
			),
			admin_url( 'admin.php' )
		);

		wp_safe_redirect( $redirect_url );
		exit;
	}

	/**
	 * Redirect to import page with success message.
	 *
	 * @since 1.0.272
	 * @param string $message Success message.
	 */
	private function redirect_with_success( $message ) {
		$redirect_url = add_query_arg(
			array(
				'page'           => 'macm-data',
				'tab'            => 'import',
				'import_success' => rawurlencode( $message ),
			),
			admin_url( 'admin.php' )
		);

		wp_safe_redirect( $redirect_url );
		exit;
	}

	/**
	 * AJAX handler to validate import file before submission.
	 *
	 * Validates the uploaded file(s), parses content, and returns
	 * a preview of what will be imported. Supports multiple CSV files.
	 *
	 * @since 1.0.265
	 * @since 1.0.271 Implemented validation logic.
	 * @since 1.0.290 Added support for multiple CSV file uploads.
	 */
	public function ajax_validate_import() {
		// Verify AJAX nonce.
		if ( ! check_ajax_referer( 'macm_data_nonce', 'nonce', false ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Security check failed.', 'martial-arts-club-manager' ),
				)
			);
		}

		// Check user capabilities.
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'You do not have permission to validate imports.', 'martial-arts-club-manager' ),
				)
			);
		}

		// Check for file upload.
		// Nonce verified above via check_ajax_referer().
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated -- Validated with isset check.
		if ( ! isset( $_FILES['import_file'] ) || ! is_array( $_FILES['import_file'] ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'No file uploaded.', 'martial-arts-club-manager' ),
				)
			);
		}

		// Verify import_file array has the required 'name' key.
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated -- Validated with isset check.
		if ( ! isset( $_FILES['import_file']['name'] ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Invalid file upload structure.', 'martial-arts-club-manager' ),
				)
			);
		}

		// Create importer instance.
		$importer = new MACM_Data_Import();

		// Check if multiple files were uploaded.
		// Note: JavaScript always sends files as import_file[] (array syntax), so name is always an array.
		// We check the actual count to determine if multiple files were selected.
		// The 'name' key existence is validated above. Sanitized in sanitize_import_file_data().
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Only checking array structure, sanitized below.
		$names_data  = $_FILES['import_file']['name'];
		$is_array    = is_array( $names_data );
		$is_multiple = $is_array && count( $names_data ) > 1;

		// Pre-sanitize file data before passing to helper methods.
		// This ensures nonce verification happens before any data access.
		// Pass true for is_multiple if it's an array (even single file from JS is array).
		$import_file_data = $this->sanitize_import_file_data( $is_array );

		// Get CSV entity from POST if provided (sanitized).
		$csv_entity = isset( $_POST['csv_entity'] ) ? sanitize_key( wp_unslash( $_POST['csv_entity'] ) ) : '';

		if ( $is_multiple ) {
			// Handle multiple file upload (2+ files).
			$this->validate_multiple_files( $importer, $import_file_data );
		} elseif ( $is_array ) {
			// Handle single file sent as array (JavaScript sends import_file[]).
			// Extract first element and treat as single file.
			$single_file_data = array(
				'name'     => $import_file_data['name'][0],
				'type'     => $import_file_data['type'][0],
				'tmp_name' => $import_file_data['tmp_name'][0],
				'error'    => $import_file_data['error'][0],
				'size'     => $import_file_data['size'][0],
			);
			$this->validate_single_file( $importer, $single_file_data, $csv_entity );
		} else {
			// Handle traditional single file upload (no array syntax).
			$this->validate_single_file( $importer, $import_file_data, $csv_entity );
		}
	}

	/**
	 * Sanitize import file data from $_FILES superglobal.
	 *
	 * Extracts and sanitizes file upload data. Must be called AFTER nonce verification.
	 * Nonce is verified in ajax_validate_import() via check_ajax_referer() before this method is called.
	 *
	 * @since 1.0.297
	 * @param bool $is_multiple Whether multiple files were uploaded.
	 * @return array Sanitized file data array.
	 */
	private function sanitize_import_file_data( $is_multiple ) {
		// Nonce verified in ajax_validate_import() at line 781 via check_ajax_referer().
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified in calling function.
		$import_file = isset( $_FILES['import_file'] ) ? wp_unslash( $_FILES['import_file'] ) : array();

		if ( $is_multiple ) {
			// Multiple files - extract and sanitize each array element.
			// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized below with sanitize_file_name.
			$names = isset( $import_file['name'] ) && is_array( $import_file['name'] ) ? wp_unslash( $import_file['name'] ) : array();
			// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized below with sanitize_mime_type.
			$types = isset( $import_file['type'] ) && is_array( $import_file['type'] ) ? wp_unslash( $import_file['type'] ) : array();
			// tmp_name validated with is_uploaded_file() in validate_file() method.
			$tmp_names = isset( $import_file['tmp_name'] ) && is_array( $import_file['tmp_name'] ) ? $import_file['tmp_name'] : array();
			$errors    = isset( $import_file['error'] ) && is_array( $import_file['error'] ) ? $import_file['error'] : array();
			$sizes     = isset( $import_file['size'] ) && is_array( $import_file['size'] ) ? $import_file['size'] : array();

			return array(
				'name'     => array_map( 'sanitize_file_name', $names ),
				'type'     => array_map( 'sanitize_mime_type', $types ),
				'tmp_name' => array_map( array( $this, 'validate_tmp_name' ), $tmp_names ),
				'error'    => array_map( 'absint', $errors ),
				'size'     => array_map( 'absint', $sizes ),
			);
		}

		// Single file - extract and sanitize directly.
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized below with sanitize_file_name.
		$name = isset( $import_file['name'] ) ? sanitize_file_name( wp_unslash( $import_file['name'] ) ) : '';
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized below with sanitize_mime_type.
		$type     = isset( $import_file['type'] ) ? sanitize_mime_type( wp_unslash( $import_file['type'] ) ) : '';
		$tmp_name = isset( $import_file['tmp_name'] ) ? $this->validate_tmp_name( $import_file['tmp_name'] ) : '';
		$error    = isset( $import_file['error'] ) ? absint( $import_file['error'] ) : UPLOAD_ERR_NO_FILE;
		$size     = isset( $import_file['size'] ) ? absint( $import_file['size'] ) : 0;

		return array(
			'name'     => $name,
			'type'     => $type,
			'tmp_name' => $tmp_name,
			'error'    => $error,
			'size'     => $size,
		);
	}

	/**
	 * Validate tmp_name path from file upload.
	 *
	 * @since 1.0.297
	 * @param string $tmp_name The temporary file path.
	 * @return string Validated path or empty string if invalid.
	 */
	private function validate_tmp_name( $tmp_name ) {
		if ( ! is_string( $tmp_name ) ) {
			return '';
		}
		// is_uploaded_file() validates the path is a legitimate uploaded file.
		return is_uploaded_file( $tmp_name ) ? $tmp_name : '';
	}

	/**
	 * Validate a single uploaded file.
	 *
	 * @since 1.0.290
	 * @since 1.0.297 Accept pre-sanitized file data and csv_entity as parameters.
	 * @param MACM_Data_Import $importer    Import handler instance.
	 * @param array            $import_file Pre-sanitized file data array.
	 * @param string           $csv_entity  Pre-sanitized CSV entity type from POST.
	 */
	private function validate_single_file( $importer, $import_file, $csv_entity = '' ) {
		// Validate the uploaded file.
		$validation = $importer->validate_file( $import_file );

		if ( is_wp_error( $validation ) ) {
			wp_send_json_error(
				array(
					'message' => $validation->get_error_message(),
					'code'    => $validation->get_error_code(),
				)
			);
		}

		// Verify file array has required keys before accessing.
		if ( empty( $import_file['tmp_name'] ) || empty( $import_file['name'] ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Invalid file upload structure.', 'martial-arts-club-manager' ),
				)
			);
		}

		// Get file info from sanitized array.
		$file_path = $import_file['tmp_name'];
		$file_name = $import_file['name'];
		$file_size = $import_file['size'];
		$extension = strtolower( pathinfo( $file_name, PATHINFO_EXTENSION ) );

		// Parse the file based on type.
		if ( 'json' === $extension ) {
			$data = $importer->parse_json( $file_path );
		} else {
			// For CSV, use the entity type from the request or detect from filename.
			$entity = 'members';
			if ( ! empty( $csv_entity ) ) {
				$entity = $csv_entity;
			} elseif ( preg_match( '/macm-(\w+)-/', $file_name, $matches ) ) {
				$entity = $matches[1];
			}
			$data = $importer->parse_csv( $file_path, $entity );
		}

		if ( is_wp_error( $data ) ) {
			wp_send_json_error(
				array(
					'message' => $data->get_error_message(),
					'code'    => $data->get_error_code(),
				)
			);
		}

		// Get import preview.
		$preview = $importer->get_import_preview( $data );

		// Add file info to response.
		$preview['file'] = array(
			'name' => $file_name,
			'size' => size_format( $file_size ),
			'type' => $extension,
		);

		// Store parsed data in transient for the actual import.
		// Include user ID in transient key for additional security.
		$import_id = wp_generate_uuid4();
		$user_id   = get_current_user_id();
		set_transient( 'macm_import_' . $user_id . '_' . $import_id, $data, HOUR_IN_SECONDS );

		$preview['import_id'] = $import_id;

		wp_send_json_success( $preview );
	}

	/**
	 * Validate multiple uploaded CSV files.
	 *
	 * Merges data from multiple CSV files into a single import.
	 * Each CSV file should contain data for a different entity type.
	 *
	 * @since 1.0.290
	 * @since 1.0.297 Accept pre-sanitized file data as parameter.
	 * @param MACM_Data_Import $importer         Import handler instance.
	 * @param array            $import_file_data Pre-sanitized file data array with arrays for each field.
	 */
	private function validate_multiple_files( $importer, $import_file_data ) {
		$file_names = $import_file_data['name'];
		$file_types = $import_file_data['type'];
		$file_tmps  = $import_file_data['tmp_name'];
		$file_errs  = $import_file_data['error'];
		$file_sizes = $import_file_data['size'];

		$file_count = count( $file_names );

		if ( 0 === $file_count ) {
			wp_send_json_error(
				array(
					'message' => __( 'No files uploaded.', 'martial-arts-club-manager' ),
				)
			);
		}

		// Don't allow JSON files when multiple files are selected.
		foreach ( $file_names as $name ) {
			$ext = strtolower( pathinfo( $name, PATHINFO_EXTENSION ) );
			if ( 'json' === $ext ) {
				wp_send_json_error(
					array(
						'message' => __( 'JSON files cannot be combined with other files. Please upload either a single JSON file or multiple CSV files.', 'martial-arts-club-manager' ),
					)
				);
			}
		}

		// Validate and parse each file.
		$merged_data   = array();
		$total_size    = 0;
		$parsed_files  = array();
		$skipped_files = array();
		$warnings      = array();

		for ( $i = 0; $i < $file_count; $i++ ) {
			$import_file = array(
				'name'     => $file_names[ $i ],
				'type'     => $file_types[ $i ],
				'tmp_name' => $file_tmps[ $i ],
				'error'    => $file_errs[ $i ],
				'size'     => $file_sizes[ $i ],
			);

			// Validate the file.
			$validation = $importer->validate_file( $import_file );

			if ( is_wp_error( $validation ) ) {
				wp_send_json_error(
					array(
						'message' => sprintf(
							/* translators: 1: file name, 2: error message */
							__( 'Error in file "%1$s": %2$s', 'martial-arts-club-manager' ),
							$import_file['name'],
							$validation->get_error_message()
						),
					)
				);
			}

			// Detect entity type from filename.
			$entity = 'members';
			if ( preg_match( '/macm-(\w+)-/', $import_file['name'], $matches ) ) {
				$entity = $matches[1];
			}

			// Parse the CSV file.
			$data = $importer->parse_csv( $import_file['tmp_name'], $entity );

			// Skip empty files with a warning instead of failing.
			if ( is_wp_error( $data ) ) {
				$error_code = $data->get_error_code();

				// Only skip "empty CSV" errors, fail on other parsing errors.
				if ( 'empty_csv' === $error_code ) {
					$skipped_files[] = $import_file['name'];
					$warnings[]      = sprintf(
						/* translators: %s: file name */
						__( 'Skipped "%s": No data rows found (file may be empty or contain only headers).', 'martial-arts-club-manager' ),
						$import_file['name']
					);
					continue;
				}

				// Other parsing errors should fail.
				wp_send_json_error(
					array(
						'message' => sprintf(
							/* translators: 1: file name, 2: error message */
							__( 'Error parsing file "%1$s": %2$s', 'martial-arts-club-manager' ),
							$import_file['name'],
							$data->get_error_message()
						),
					)
				);
			}

			// Check for duplicate entity types.
			if ( isset( $merged_data[ $entity ] ) ) {
				$warnings[] = sprintf(
					/* translators: 1: entity type, 2: file name */
					__( 'Multiple files for "%1$s" detected. Data from "%2$s" will be appended.', 'martial-arts-club-manager' ),
					$entity,
					$import_file['name']
				);
				// Merge arrays for the same entity.
				$merged_data[ $entity ] = array_merge( $merged_data[ $entity ], $data[ $entity ] );
			} else {
				// Merge data from this file.
				$merged_data = array_merge( $merged_data, $data );
			}

			$total_size    += $import_file['size'];
			$parsed_files[] = $import_file['name'];
		}

		// Fail if all files were skipped (no data to import).
		if ( empty( $merged_data ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'No data to import. All CSV files were empty or contained only headers.', 'martial-arts-club-manager' ),
				)
			);
		}

		// Get import preview for merged data.
		$preview = $importer->get_import_preview( $merged_data );

		// Add file info to response.
		$preview['file'] = array(
			'name'  => sprintf(
				/* translators: %d: number of files */
				_n( '%d CSV file', '%d CSV files', $file_count, 'martial-arts-club-manager' ),
				$file_count
			),
			'size'  => size_format( $total_size ),
			'type'  => 'csv',
			'files' => $parsed_files,
		);

		// Add warnings if any.
		if ( ! empty( $warnings ) ) {
			if ( ! isset( $preview['warnings'] ) ) {
				$preview['warnings'] = array();
			}
			$preview['warnings'] = array_merge( $preview['warnings'], $warnings );
		}

		// Store parsed data in transient for the actual import.
		$import_id = wp_generate_uuid4();
		$user_id   = get_current_user_id();
		set_transient( 'macm_import_' . $user_id . '_' . $import_id, $merged_data, HOUR_IN_SECONDS );

		$preview['import_id'] = $import_id;

		wp_send_json_success( $preview );
	}

	/**
	 * AJAX handler to process import after validation.
	 *
	 * Retrieves previously validated import data from transient and runs the import.
	 *
	 * @since 1.0.272
	 */
	public function ajax_process_import() {
		// Verify AJAX nonce.
		if ( ! check_ajax_referer( 'macm_data_nonce', 'nonce', false ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Security check failed.', 'martial-arts-club-manager' ),
				)
			);
		}

		// Check user capabilities.
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'You do not have permission to import data.', 'martial-arts-club-manager' ),
				)
			);
		}

		// Get import_id from request.
		if ( ! isset( $_POST['import_id'] ) || empty( $_POST['import_id'] ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Invalid import request. Please validate the file first.', 'martial-arts-club-manager' ),
				)
			);
		}

		$import_id = sanitize_key( $_POST['import_id'] );
		$user_id   = get_current_user_id();

		// Retrieve import data from transient (includes user ID for security).
		$data = get_transient( 'macm_import_' . $user_id . '_' . $import_id );

		if ( false === $data ) {
			wp_send_json_error(
				array(
					'message' => __( 'Import session expired. Please upload the file again.', 'martial-arts-club-manager' ),
				)
			);
		}

		// Get import options.
		$options = array(
			'user_mapping'        => isset( $_POST['user_mapping'] ) ? sanitize_key( $_POST['user_mapping'] ) : 'match_email',
			'conflict_resolution' => isset( $_POST['conflict_resolution'] ) ? sanitize_key( $_POST['conflict_resolution'] ) : 'skip',
		);

		// Validate options.
		$valid_user_mappings = array( 'match_email', 'assign_current', 'skip_unmatched' );
		if ( ! in_array( $options['user_mapping'], $valid_user_mappings, true ) ) {
			$options['user_mapping'] = 'match_email';
		}

		$valid_conflict_modes = array( 'skip', 'update', 'create' );
		if ( ! in_array( $options['conflict_resolution'], $valid_conflict_modes, true ) ) {
			$options['conflict_resolution'] = 'skip';
		}

		// Create importer and run import.
		$importer = new MACM_Data_Import();
		$results  = $importer->import( $data, $options );

		// Delete the transient after use.
		delete_transient( 'macm_import_' . $user_id . '_' . $import_id );

		if ( is_wp_error( $results ) ) {
			wp_send_json_error(
				array(
					'message' => $results->get_error_message(),
				)
			);
		}

		// Build success response.
		$total_imported = 0;
		$total_updated  = 0;
		$total_skipped  = 0;
		$entity_results = array();

		if ( isset( $results['entity_results'] ) ) {
			foreach ( $results['entity_results'] as $entity => $entity_result ) {
				$imported = $entity_result['imported'] ?? 0;
				$updated  = $entity_result['updated'] ?? 0;
				$skipped  = $entity_result['skipped'] ?? 0;

				$total_imported += $imported;
				$total_updated  += $updated;
				$total_skipped  += $skipped;

				$entity_results[ $entity ] = array(
					'created' => $imported,
					'updated' => $updated,
					'skipped' => $skipped,
					'errors'  => 0,
				);
			}
		}

		wp_send_json_success(
			array(
				'message'        => sprintf(
					/* translators: 1: number imported, 2: number updated, 3: number skipped */
					__( 'Import completed successfully. %1$d records imported, %2$d updated, %3$d skipped.', 'martial-arts-club-manager' ),
					$total_imported,
					$total_updated,
					$total_skipped
				),
				'total_imported' => $total_imported,
				'total_updated'  => $total_updated,
				'total_skipped'  => $total_skipped,
				'results'        => $entity_results,
			)
		);
	}

	/**
	 * AJAX handler to reset all plugin data.
	 *
	 * Truncates all plugin database tables and resets options to default.
	 * This is a destructive operation that cannot be undone.
	 *
	 * @since 1.0.266
	 */
	public function ajax_reset_plugin_data() {
		// Verify AJAX nonce.
		if ( ! check_ajax_referer( 'macm_data_nonce', 'nonce', false ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Security check failed.', 'martial-arts-club-manager' ),
				)
			);
		}

		// Check user capabilities.
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'You do not have permission to reset plugin data.', 'martial-arts-club-manager' ),
				)
			);
		}

		// Verify confirmation token was sent.
		if ( ! isset( $_POST['confirm_token'] ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Confirmation token missing.', 'martial-arts-club-manager' ),
				)
			);
		}

		$confirm_token = sanitize_text_field( wp_unslash( $_POST['confirm_token'] ) );

		if ( 'RESET' !== $confirm_token ) {
			wp_send_json_error(
				array(
					'message' => __( 'Invalid confirmation. Please type "RESET" to confirm.', 'martial-arts-club-manager' ),
				)
			);
		}

		global $wpdb;

		// List of plugin tables to truncate.
		$tables = array(
			'macm_attendance',
			'macm_belt_colors',
			'macm_class_enrollments',
			'macm_class_instructors',
			'macm_classes',
			'macm_clubs',
			'macm_event_registrations',
			'macm_events',
			'macm_grading_history',
			'macm_groups',
			'macm_instructors',
			'macm_locations',
			'macm_member_groups',
			'macm_members',
			'macm_membership_types',
			'macm_product_members',
			'macm_trial_bookings',
			'macm_videos',
		);

		$reset_count = 0;
		$errors      = array();

		// Disable foreign key checks temporarily.
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$wpdb->query( 'SET FOREIGN_KEY_CHECKS = 0' );

		foreach ( $tables as $table ) {
			$table_name = $wpdb->prefix . $table;

			// Check if table exists before truncating.
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
			$table_exists = $wpdb->get_var(
				$wpdb->prepare( 'SHOW TABLES LIKE %s', $table_name )
			);

			if ( $table_exists ) {
				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
				$result = $wpdb->query(
					// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
					"TRUNCATE TABLE `{$table_name}`"
				);

				if ( false === $result ) {
					$errors[] = $table;
				} else {
					++$reset_count;
				}
			}
		}

		// Re-enable foreign key checks.
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$wpdb->query( 'SET FOREIGN_KEY_CHECKS = 1' );

		// Clear all transient caches related to the plugin.
		delete_transient( 'macm_exportable_entities' );

		// Clear any object caches.
		wp_cache_flush();

		// Restore default data (belt colors, membership types).
		$this->restore_default_data();

		if ( ! empty( $errors ) ) {
			wp_send_json_error(
				array(
					'message'     => sprintf(
						/* translators: %d: number of tables that failed to reset */
						__( 'Reset completed with %d table(s) having errors.', 'martial-arts-club-manager' ),
						count( $errors )
					),
					'reset_count' => $reset_count,
					'errors'      => $errors,
				)
			);
		}

		wp_send_json_success(
			array(
				'message'     => __( 'All plugin data has been reset successfully. Default data restored.', 'martial-arts-club-manager' ),
				'reset_count' => $reset_count,
			)
		);
	}

	/**
	 * Restore default data after reset.
	 *
	 * Re-populates tables with default data that was created on plugin activation.
	 * Currently restores: belt colors, membership types.
	 *
	 * @since 1.0.281
	 */
	private function restore_default_data() {
		// Clear belt colors cache so initialize_defaults() will run.
		wp_cache_delete( 'macm_belt_colors_count', 'macm' );
		wp_cache_delete( 'macm_belt_colors_active', 'macm' );
		wp_cache_delete( 'macm_belt_colors_all', 'macm' );

		// Restore default belt colors.
		if ( class_exists( 'MACM_Belt_Color' ) ) {
			MACM_Belt_Color::initialize_defaults();
		} else {
			require_once MACM_PLUGIN_DIR . 'includes/classes/class-macm-belt-color.php';
			MACM_Belt_Color::initialize_defaults();
		}

		// Restore default membership types.
		$this->restore_default_membership_types();
	}

	/**
	 * Restore default membership types.
	 *
	 * Creates Basic and Premium membership types if table is empty.
	 *
	 * @since 1.0.281
	 */
	private function restore_default_membership_types() {
		global $wpdb;

		$table_name = $wpdb->prefix . 'macm_membership_types';

		// Check if table is empty.
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$count = (int) $wpdb->get_var(
			$wpdb->prepare( 'SELECT COUNT(*) FROM %i', $table_name )
		);

		if ( $count > 0 ) {
			return;
		}

		// Default membership types.
		$default_types = array(
			array(
				'type_name'   => 'Basic',
				'description' => 'Basic membership with access to regular training sessions.',
				'sort_order'  => 10,
				'is_active'   => 1,
			),
			array(
				'type_name'   => 'Premium',
				'description' => 'Premium membership with full access to all training sessions and premium content.',
				'sort_order'  => 20,
				'is_active'   => 1,
			),
		);

		foreach ( $default_types as $type ) {
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
			$wpdb->insert(
				$table_name,
				array(
					'type_name'   => $type['type_name'],
					'description' => $type['description'],
					'sort_order'  => $type['sort_order'],
					'is_active'   => $type['is_active'],
					'created_at'  => current_time( 'mysql' ),
				),
				array( '%s', '%s', '%d', '%d', '%s' )
			);
		}

		// Clear membership types cache.
		wp_cache_delete( 'macm_membership_types_active', 'macm' );
		wp_cache_delete( 'macm_membership_types_all', 'macm' );
	}
}
