<?php
/**
 * Legacy plugin migration shims (options + admin URLs).
 *
 * @package Rsmspark_Suite
 */

defined( 'ABSPATH' ) || exit;

/**
 * Migration helpers for unified rsm-* plugins upgrading from legacy installs.
 */
final class Rsmspark_Migration {

	/**
	 * New option => legacy option name(s).
	 *
	 * @var array<string, array<int, string>>
	 */
	private static $option_maps = array();

	/**
	 * Legacy admin page slug => redirect URL (relative to admin_url()).
	 *
	 * @var array<string, string>
	 */
	private static $admin_redirects = array();

	/**
	 * Whether option migration has run this request.
	 *
	 * @var bool
	 */
	private static $options_migrated = false;

	/**
	 * Whether migration hooks are registered.
	 *
	 * @var bool
	 */
	private static $initialized = false;

	/**
	 * Hooks.
	 *
	 * @return void
	 */
	public static function init() {
		if ( self::$initialized ) {
			return;
		}

		self::$initialized = true;

		add_action( 'plugins_loaded', array( __CLASS__, 'migrate_options' ), 20 );
		add_action( 'admin_init', array( __CLASS__, 'maybe_redirect_legacy_admin' ), 1 );
		add_filter( 'pre_option', array( __CLASS__, 'pre_option_legacy_fallback' ), 10, 3 );
	}

	/**
	 * Register option aliases for a plugin.
	 *
	 * @param array<string, string|array<int, string>> $map New option => legacy option(s).
	 * @return void
	 */
	public static function map_options( $map ) {
		foreach ( $map as $new_key => $legacy_keys ) {
			if ( is_string( $legacy_keys ) ) {
				$legacy_keys = array( $legacy_keys );
			}
			if ( ! isset( self::$option_maps[ $new_key ] ) ) {
				self::$option_maps[ $new_key ] = array();
			}
			self::$option_maps[ $new_key ] = array_merge( self::$option_maps[ $new_key ], (array) $legacy_keys );
		}
	}

	/**
	 * Register legacy wp-admin page slug redirects.
	 *
	 * @param array<string, string> $redirects Legacy `page` query value => target admin URL path.
	 * @return void
	 */
	public static function map_admin_pages( $redirects ) {
		self::$admin_redirects = array_merge( self::$admin_redirects, $redirects );
	}

	/**
	 * Copy legacy options into new keys when the new key is unset.
	 *
	 * @return void
	 */
	public static function migrate_options() {
		if ( self::$options_migrated || empty( self::$option_maps ) ) {
			return;
		}

		self::$options_migrated = true;

		foreach ( self::$option_maps as $new_key => $legacy_keys ) {
			if ( false !== get_option( $new_key, false ) ) {
				continue;
			}

			foreach ( $legacy_keys as $legacy_key ) {
				$legacy_value = get_option( $legacy_key, false );
				if ( false !== $legacy_value ) {
					update_option( $new_key, $legacy_value );
					break;
				}
			}
		}
	}

	/**
	 * Read-through fallback when a new option has not been migrated yet.
	 *
	 * @param mixed  $pre_option Pre-filtered value.
	 * @param string $option     Option name.
	 * @param mixed  $default    Default value.
	 * @return mixed
	 */
	public static function pre_option_legacy_fallback( $pre_option, $option, $default ) {
		if ( null !== $pre_option || ! isset( self::$option_maps[ $option ] ) ) {
			return $pre_option;
		}

		foreach ( self::$option_maps[ $option ] as $legacy_key ) {
			$legacy_value = get_option( $legacy_key, false );
			if ( false !== $legacy_value ) {
				return $legacy_value;
			}
		}

		return $pre_option;
	}

	/**
	 * Redirect bookmarked legacy admin URLs to unified suite pages.
	 *
	 * @return void
	 */
	public static function maybe_redirect_legacy_admin() {
		if ( ! is_admin() || empty( self::$admin_redirects ) ) {
			return;
		}

		// phpcs:disable WordPress.Security.NonceVerification.Recommended -- Read-only legacy admin redirect parameters; no state change.
		$page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( (string) $_GET['page'] ) ) : '';

		if ( '' === $page || ! isset( self::$admin_redirects[ $page ] ) ) {
			return;
		}

		$target = self::$admin_redirects[ $page ];
		$args   = array();

		if ( isset( $_GET['tab'] ) ) {
			$args['tab'] = sanitize_key( wp_unslash( (string) $_GET['tab'] ) );
		}

		foreach ( array(
			'updated',
			'settings-updated',
			'adv_err',
			'purged',
			'reset',
			'cache_cleared',
			'openrsm_import',
			'openrsm_import_token',
			'calendar_id',
			'message',
			'rsm_import',
			'rsm_msg',
			'rsmspark_import',
			'rsmspark_msg',
			'ed_import',
			'c',
			'u',
		) as $key ) {
			if ( isset( $_GET[ $key ] ) ) {
				$args[ $key ] = 'c' === $key || 'u' === $key
					? absint( wp_unslash( $_GET[ $key ] ) )
					: sanitize_text_field( wp_unslash( (string) $_GET[ $key ] ) );
			}
		}
		// phpcs:enable WordPress.Security.NonceVerification.Recommended

		$url = admin_url( $target );
		if ( ! empty( $args ) ) {
			$url = add_query_arg( $args, $url );
		}

		wp_safe_redirect( $url );
		exit;
	}

	/**
	 * Build a settings redirect URL preserving the active tab.
	 *
	 * @param string $page_slug Settings page slug.
	 * @param string $default_tab Default tab id.
	 * @param array<string, scalar> $extra Extra query args.
	 * @return string
	 */
	public static function settings_url( $page_slug, $default_tab = 'general', $extra = array() ) {
		$tab = $default_tab;

		// phpcs:disable WordPress.Security.NonceVerification.Recommended -- Read-only admin navigation parameters; no state change.
		if ( isset( $_GET['tab'] ) && isset( $_GET['page'] ) && $page_slug === sanitize_key( wp_unslash( (string) $_GET['page'] ) ) ) {
			$tab = sanitize_key( wp_unslash( (string) $_GET['tab'] ) );
		}
		// phpcs:enable WordPress.Security.NonceVerification.Recommended

		// phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce verified in caller via check_ajax_referer/check_admin_referer.
		if ( isset( $_POST['rsmspark_settings_tab'] ) ) {
			$tab = sanitize_key( wp_unslash( (string) $_POST['rsmspark_settings_tab'] ) );
		} elseif ( isset( $_POST['rsm_settings_tab'] ) ) {
			$tab = sanitize_key( wp_unslash( (string) $_POST['rsm_settings_tab'] ) );
		}
		// phpcs:enable WordPress.Security.NonceVerification.Missing

		$args = array_merge(
			array(
				'page' => $page_slug,
				'tab'  => $tab,
			),
			$extra
		);

		return add_query_arg( $args, admin_url( 'admin.php' ) );
	}
}
