<?php
/**
 * Background Migration to Custom Tables.
 *
 * @package    Extra_Product_Options_For_WooCommerce
 * @subpackage Extra_Product_Options_For_WooCommerce/includes
 * @since      4.4.0
 */

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

// Require WP_Background_Process first if it doesn't exist.
if ( ! class_exists( 'WP_Background_Process', false ) ) {
	$epofw_wp_bg_process_file = WP_PLUGIN_DIR . '/woocommerce/includes/libraries/wp-background-process.php';
	if ( file_exists( $epofw_wp_bg_process_file ) ) {
		include_once $epofw_wp_bg_process_file;
	}
}

if ( ! class_exists( 'WC_Background_Process', false ) ) {
	$epofw_wc_bg_process_file = WP_PLUGIN_DIR . '/woocommerce/includes/abstracts/class-wc-background-process.php';
	if ( file_exists( $epofw_wc_bg_process_file ) ) {
		include_once $epofw_wc_bg_process_file;
	}
}

// Bail if WC_Background_Process is still not available.
if ( ! class_exists( 'WC_Background_Process', false ) ) {
	return;
}

/**
 * EPOFW_Bg_Migration class.
 *
 * Handles background migration from post meta to custom tables.
 */
class EPOFW_Bg_Migration extends WC_Background_Process {

	/**
	 * Action name.
	 *
	 * @var string
	 */
	protected $action = 'epofw_bg_migration_to_custom_tables';

	/**
	 * Single instance of this class.
	 *
	 * @var EPOFW_Bg_Migration
	 */
	private static $instance = null;

	/**
	 * Get single instance.
	 *
	 * @return EPOFW_Bg_Migration
	 */
	public static function get_instance() {
		if ( is_null( self::$instance ) ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Task to migrate a single addon from post meta to custom tables.
	 *
	 * @param mixed $item The addon ID (int) or array with blog_id and addon_id (multisite).
	 *
	 * @return mixed False to remove from queue, or item to retry.
	 */
	protected function task( $item ) {
		// Handle multisite: extract blog_id and addon_id.
		$blog_id  = null;
		$addon_id = null;

		if ( is_array( $item ) && isset( $item['blog_id'] ) && isset( $item['addon_id'] ) ) {
			$blog_id  = (int) $item['blog_id'];
			$addon_id = (int) $item['addon_id'];

			// Switch to the correct blog context.
			switch_to_blog( $blog_id );
		} else {
			// Single site: item is the addon ID directly.
			$addon_id = (int) $item;
		}

		try {
			// Check if already migrated.
			if ( get_post_meta( $addon_id, 'epofw_migrated_to_custom_tables', true ) ) {
				if ( $blog_id ) {
					restore_current_blog();
				}
				return false;
			}

			// Check if data already exists in custom tables.
			$existing_data = EPOFW_Custom_Tables::load_addon( $addon_id );
			if ( ! empty( $existing_data ) ) {
				// Mark as migrated and skip.
				update_post_meta( $addon_id, 'epofw_migrated_to_custom_tables', true );
				if ( $blog_id ) {
					restore_current_blog();
				}
				return false;
			}

			// Get data from post meta.
			$addon_data = get_post_meta( $addon_id, 'epofw_prd_opt_data', true );

			if ( empty( $addon_data ) ) {
				// No data to migrate, mark as complete.
				update_post_meta( $addon_id, 'epofw_migrated_to_custom_tables', true );
				if ( $blog_id ) {
					restore_current_blog();
				}
				return false;
			}

			// Transform data if needed (handle old structure).
			$transformed_data = $this->transform_data_structure( $addon_data );

			// Save to custom tables.
			$result = EPOFW_Custom_Tables::save_addon( $addon_id, $transformed_data );

			if ( $result ) {
				// Mark as migrated.
				update_post_meta( $addon_id, 'epofw_migrated_to_custom_tables', true );

				// Keep old post meta for backward compatibility (rollback to older version).
				// phpcs:ignore Squiz.PHP.CommentedOutCode.Found -- Intentionally kept for reference.

				// Update migration count (network-wide option for multisite).
				$count = get_option( 'epofw_custom_table_migration_count', 0 );
				update_option( 'epofw_custom_table_migration_count', $count + 1 );
			}
		} finally {
			// Always restore blog context if we switched.
			if ( $blog_id ) {
				restore_current_blog();
			}
		}

		return false;
	}

	/**
	 * Transform old data structure to new structure if needed.
	 *
	 * Uses EPOFW_Migration class to properly transform old flat structure
	 * to new hierarchical structure where each field gets its own row_group.
	 *
	 * @param array $addon_data The addon data.
	 *
	 * @return array Transformed data.
	 */
	private function transform_data_structure( $addon_data ) {
		// Use the EPOFW_Migration class for proper transformation.
		if ( class_exists( 'EPOFW_Migration' ) ) {
			// Check if old flat structure and transform.
			if ( EPOFW_Migration::is_old_flat_structure( $addon_data ) ) {
				return EPOFW_Migration::transform_to_new_structure( $addon_data );
			}
		}

		return $addon_data;
	}

	/**
	 * Complete the migration process.
	 */
	protected function complete() {
		parent::complete();

		// Mark migration as complete (both options for consistency).
		update_option( 'epofw_custom_table_migration_complete', true );
		update_option( 'epofw_row_association_migration_done', true );
		update_option( 'epofw_custom_table_migration_completed_at', current_time( 'mysql' ) );

		// Clear the running transient.
		delete_transient( 'epofw_custom_table_migration_running' );
	}

	/**
	 * Check if migration is running.
	 *
	 * @return bool
	 */
	public function is_migrating() {
		return $this->is_processing() || ! $this->is_queue_empty();
	}
}
