<?php
/**
 * Schema Architecture V2 migration notice, review report, and secure restore UI.
 *
 * @package SEOvaultSEO\Admin
 */

namespace SEOvaultSEO\Admin;

use SEOvaultSEO\Schema\SchemaMigration;

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

/**
 * Admin notice + review/restore surfaces for Schema V2 migration.
 */
class SchemaMigrationAdmin {

	/**
	 * Review / restore admin page slug.
	 */
	const PAGE_SLUG = 'seovault-ai-schema-migration';

	/**
	 * admin-post action: dismiss notice (backup retained).
	 */
	const ACTION_DISMISS = 'seovaultseo_schema_v2_notice_dismiss';

	/**
	 * admin-post action: restore from verified backup.
	 */
	const ACTION_RESTORE = 'seovaultseo_schema_v2_restore';

	/**
	 * admin-post action: clear restore pause and re-run migration.
	 */
	const ACTION_REMIGRATE = 'seovaultseo_schema_v2_remigrate';

	/**
	 * Nonce action for dismiss.
	 */
	const NONCE_DISMISS = 'seovaultseo_schema_v2_notice_dismiss';

	/**
	 * Nonce action for restore.
	 */
	const NONCE_RESTORE = 'seovaultseo_schema_v2_restore';

	/**
	 * Nonce action for remigrate.
	 */
	const NONCE_REMIGRATE = 'seovaultseo_schema_v2_remigrate';

	/**
	 * Register hooks.
	 *
	 * @return void
	 */
	public static function init() {
		// The migration notice is now owned by the Action Center and removed
		// from the global admin_notices stream.
		add_action( 'admin_menu', array( __CLASS__, 'register_menu' ), 25 );
		add_action( 'admin_post_' . self::ACTION_DISMISS, array( __CLASS__, 'handle_dismiss' ) );
		add_action( 'admin_post_' . self::ACTION_RESTORE, array( __CLASS__, 'handle_restore' ) );
		add_action( 'admin_post_' . self::ACTION_REMIGRATE, array( __CLASS__, 'handle_remigrate' ) );
	}

	/**
	 * Capability required for notice / review / restore.
	 *
	 * @return string
	 */
	public static function required_capability() {
		return (string) apply_filters( 'seovaultseo_main_menu_capability', 'manage_options' );
	}

	/**
	 * Whether the current user may manage the migration notice/restore UI.
	 *
	 * @return bool
	 */
	public static function current_user_can_manage() {
		return current_user_can( self::required_capability() );
	}

	/**
	 * Review page URL.
	 *
	 * @param array $args Optional query args.
	 * @return string
	 */
	public static function review_url( array $args = array() ) {
		$args = array_merge(
			array(
				'page' => self::PAGE_SLUG,
			),
			$args
		);
		return add_query_arg( $args, admin_url( 'admin.php' ) );
	}

	/**
	 * Schema settings URL (General → Schema tab).
	 *
	 * @return string
	 */
	public static function schema_settings_url() {
		return admin_url( 'admin.php?page=seovault-ai-general&tab=vtab-schema' );
	}

	/**
	 * Register review submenu while a verified backup exists (rollback window).
	 *
	 * @return void
	 */
	public static function register_menu() {
		if ( ! self::current_user_can_manage() ) {
			return;
		}

		if ( ! SchemaMigration::is_restore_available() && ! SchemaMigration::should_show_notice() ) {
			$state = SchemaMigration::get_notice_state();
			if ( ! in_array( (string) ( $state['status'] ?? '' ), array( SchemaMigration::NOTICE_PENDING, SchemaMigration::NOTICE_DISMISSED, SchemaMigration::NOTICE_RESTORED ), true ) ) {
				return;
			}
		}

		add_submenu_page(
			'seovault-ai',
			__( 'Schema Migration', 'seovault-ai' ),
			__( 'Schema Migration', 'seovault-ai' ),
			self::required_capability(),
			self::PAGE_SLUG,
			array( __CLASS__, 'render_review_page' )
		);
	}

	/**
	 * One-time admin notice (Section 10.5).
	 *
	 * @return void
	 */
	public static function render_notice() {
		if ( ! self::current_user_can_manage() ) {
			return;
		}

		if ( ! SchemaMigration::should_show_notice() ) {
			return;
		}

		$review_url   = self::review_url();
		$settings_url = self::schema_settings_url();
		$dismiss_url  = wp_nonce_url(
			admin_url( 'admin-post.php?action=' . self::ACTION_DISMISS ),
			self::NONCE_DISMISS
		);
		?>
		<div class="notice notice-info seovaultseo-notice seovaultseo-notice-schema-v2-migration" role="status">
			<div class="seovaultseo-notice-icon">
				<span class="dashicons dashicons-database" aria-hidden="true"></span>
			</div>
			<div class="seovaultseo-notice-content">
				<p>
					<strong><?php esc_html_e( 'SEOvault schema update', 'seovault-ai' ); ?></strong>
				</p>
				<p>
					<?php
					esc_html_e(
						'SEOvault updated your schema setup. Older versions could apply optional schema such as Recipe, Event, and Course to ordinary posts. We switched to safer automatic defaults and preserved your previous configuration.',
						'seovault-ai'
					);
					?>
				</p>
				<p>
					<a href="<?php echo esc_url( $settings_url ); ?>" class="button button-secondary">
						<?php esc_html_e( 'Review schema settings', 'seovault-ai' ); ?>
					</a>
					<a href="<?php echo esc_url( $review_url ); ?>" class="button button-primary">
						<?php esc_html_e( 'Review converted drafts/templates', 'seovault-ai' ); ?>
					</a>
					<a href="<?php echo esc_url( $review_url ); ?>#seovault-schema-v2-restore" class="button button-secondary">
						<?php esc_html_e( 'Restore previous configuration', 'seovault-ai' ); ?>
					</a>
					<a href="<?php echo esc_url( $dismiss_url ); ?>" class="button button-link">
						<?php esc_html_e( 'Dismiss', 'seovault-ai' ); ?>
					</a>
				</p>
			</div>
		</div>
		<?php
	}

	/**
	 * Render the review report + restore form.
	 *
	 * @return void
	 */
	public static function render_review_page() {
		if ( ! self::current_user_can_manage() ) {
			wp_die( esc_html__( 'You do not have permission to manage schema migration.', 'seovault-ai' ) );
		}

		$summary  = SchemaMigration::get_review_summary();
		$message  = isset( $_GET['sv2_msg'] ) ? sanitize_key( wp_unslash( $_GET['sv2_msg'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only flash key.
		$flash    = self::flash_message( $message );
		$entries  = isset( $summary['global']['entries'] ) && is_array( $summary['global']['entries'] ) ? $summary['global']['entries'] : array();
		$posts    = isset( $summary['posts'] ) && is_array( $summary['posts'] ) ? $summary['posts'] : array();
		$backup   = isset( $summary['backup'] ) && is_array( $summary['backup'] ) ? $summary['backup'] : array();
		$warnings = isset( $summary['restore_consequences'] ) && is_array( $summary['restore_consequences'] ) ? $summary['restore_consequences'] : array();
		$can_restore = ! empty( $backup['available'] );
		$paused      = ! empty( $summary['auto_migration_paused'] );
		$notice      = isset( $summary['notice'] ) && is_array( $summary['notice'] ) ? $summary['notice'] : array();
		$restored    = SchemaMigration::NOTICE_RESTORED === (string) ( $notice['status'] ?? '' );
		?>
		<div class="wrap seovaultseo-schema-v2-migration-review">
			<h1><?php esc_html_e( 'Schema migration review', 'seovault-ai' ); ?></h1>

			<?php if ( is_array( $flash ) ) : ?>
				<div class="notice notice-<?php echo esc_attr( $flash['type'] ); ?> is-dismissible">
					<p><?php echo esc_html( $flash['text'] ); ?></p>
				</div>
			<?php endif; ?>

			<?php if ( $paused ) : ?>
				<div class="notice notice-success inline">
					<p>
						<strong><?php esc_html_e( 'Previous configuration restored', 'seovault-ai' ); ?></strong>
						<?php
						esc_html_e(
							'Automatic remigration is paused so your restored global schema configuration stays in place. Use “Re-run schema migration” below when you want to migrate to Architecture V2 again.',
							'seovault-ai'
						);
						?>
					</p>
				</div>
			<?php endif; ?>

			<p>
				<?php
				esc_html_e(
					'This report lists converted and withheld schema items from the Architecture V2 migration. Raw schema field bodies and site secrets are never shown here.',
					'seovault-ai'
				);
				?>
			</p>

			<h2><?php esc_html_e( 'Global specialized changes', 'seovault-ai' ); ?></h2>
			<?php if ( empty( $entries ) ) : ?>
				<p><?php esc_html_e( 'No converted or withheld global specialized entries were recorded.', 'seovault-ai' ); ?></p>
			<?php else : ?>
				<table class="widefat striped">
					<thead>
						<tr>
							<th scope="col"><?php esc_html_e( 'Type', 'seovault-ai' ); ?></th>
							<th scope="col"><?php esc_html_e( 'Entry ID', 'seovault-ai' ); ?></th>
							<th scope="col"><?php esc_html_e( 'Targeting', 'seovault-ai' ); ?></th>
							<th scope="col"><?php esc_html_e( 'Result', 'seovault-ai' ); ?></th>
						</tr>
					</thead>
					<tbody>
						<?php foreach ( $entries as $entry ) : ?>
							<tr>
								<td><?php echo esc_html( (string) ( $entry['type'] ?? '' ) ); ?></td>
								<td><code><?php echo esc_html( (string) ( $entry['id'] ?? '' ) ); ?></code></td>
								<td><?php echo esc_html( (string) ( $entry['targeting'] ?? '' ) ); ?></td>
								<td><?php echo esc_html( (string) ( $entry['label'] ?? '' ) ); ?></td>
							</tr>
						<?php endforeach; ?>
					</tbody>
				</table>
			<?php endif; ?>

			<h2><?php esc_html_e( 'Per-post migration summary', 'seovault-ai' ); ?></h2>
			<ul>
				<li>
					<?php
					printf(
						/* translators: %s: status string */
						esc_html__( 'Status: %s', 'seovault-ai' ),
						esc_html( (string) ( $posts['status'] ?? '' ) )
					);
					?>
				</li>
				<li>
					<?php
					printf(
						/* translators: %d: count */
						esc_html__( 'Ready instances converted: %d', 'seovault-ai' ),
						(int) ( $posts['converted_ready'] ?? 0 )
					);
					?>
				</li>
				<li>
					<?php
					printf(
						/* translators: %d: count */
						esc_html__( 'Unfinished drafts withheld from publish: %d', 'seovault-ai' ),
						(int) ( $posts['converted_draft'] ?? 0 )
					);
					?>
				</li>
				<li>
					<?php
					printf(
						/* translators: %d: count */
						esc_html__( 'Valid custom JSON kept (replace mode): %d', 'seovault-ai' ),
						(int) ( $posts['custom_valid'] ?? 0 )
					);
					?>
				</li>
				<li>
					<?php
					printf(
						/* translators: %d: count */
						esc_html__( 'Invalid custom JSON backed up and withheld: %d', 'seovault-ai' ),
						(int) ( $posts['custom_invalid'] ?? 0 )
					);
					?>
				</li>
			</ul>

			<p>
				<a class="button button-secondary" href="<?php echo esc_url( self::schema_settings_url() ); ?>">
					<?php esc_html_e( 'Open schema settings', 'seovault-ai' ); ?>
				</a>
			</p>

			<?php if ( $paused || $restored ) : ?>
				<hr />
				<div id="seovault-schema-v2-remigrate" tabindex="-1">
					<h2><?php esc_html_e( 'Re-run schema migration', 'seovault-ai' ); ?></h2>
					<p>
						<?php
						esc_html_e(
							'This applies Architecture V2 transforms again to the current global schema configuration. Specialized types with broad targeting may be retired or converted to templates.',
							'seovault-ai'
						);
						?>
					</p>
					<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
						<input type="hidden" name="action" value="<?php echo esc_attr( self::ACTION_REMIGRATE ); ?>" />
						<?php wp_nonce_field( self::NONCE_REMIGRATE ); ?>
						<p>
							<label for="seovault_schema_v2_remigrate_confirm">
								<input
									type="checkbox"
									name="seovault_schema_v2_remigrate_confirm"
									id="seovault_schema_v2_remigrate_confirm"
									value="1"
									required
								/>
								<?php esc_html_e( 'I understand this will re-run Schema Architecture V2 migration on the current configuration.', 'seovault-ai' ); ?>
							</label>
						</p>
						<?php submit_button( __( 'Re-run schema migration', 'seovault-ai' ), 'primary', 'submit', false ); ?>
					</form>
				</div>
			<?php endif; ?>

			<hr />

			<div id="seovault-schema-v2-restore" tabindex="-1">
				<h2><?php esc_html_e( 'Restore previous configuration', 'seovault-ai' ); ?></h2>

				<?php if ( ! $can_restore ) : ?>
					<p><?php esc_html_e( 'No verified migration backup is available on this site.', 'seovault-ai' ); ?></p>
				<?php else : ?>
					<div class="notice notice-warning inline">
						<p><strong><?php esc_html_e( 'Restoring legacy behavior', 'seovault-ai' ); ?></strong></p>
						<ul>
							<?php foreach ( $warnings as $line ) : ?>
								<li><?php echo esc_html( (string) $line ); ?></li>
							<?php endforeach; ?>
						</ul>
					</div>

					<p>
						<?php
						printf(
							/* translators: 1: backup created_at, 2: short checksum */
							esc_html__( 'Verified backup created %1$s (checksum %2$s).', 'seovault-ai' ),
							esc_html( (string) ( $backup['created_at'] ?? '' ) ),
							esc_html( substr( (string) ( $backup['checksum'] ?? '' ), 0, 12 ) )
						);
						?>
					</p>

					<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
						<input type="hidden" name="action" value="<?php echo esc_attr( self::ACTION_RESTORE ); ?>" />
						<?php wp_nonce_field( self::NONCE_RESTORE ); ?>
						<p>
							<label for="seovault_schema_v2_restore_confirm">
								<input
									type="checkbox"
									name="seovault_schema_v2_restore_confirm"
									id="seovault_schema_v2_restore_confirm"
									value="1"
									required
								/>
								<?php esc_html_e( 'I understand this will restore the previous global schema configuration and may re-enable specialized schema on ordinary posts.', 'seovault-ai' ); ?>
							</label>
						</p>
						<?php submit_button( __( 'Restore previous configuration', 'seovault-ai' ), 'delete', 'submit', false ); ?>
					</form>
				<?php endif; ?>
			</div>
		</div>
		<?php
	}

	/**
	 * Map flash query keys to user-facing messages.
	 *
	 * @param string $key Flash key.
	 * @return array{type:string,text:string}|null
	 */
	public static function flash_message( $key ) {
		$key = (string) $key;
		$map = array(
			'dismissed'              => array(
				'type' => 'success',
				'text' => __( 'Schema migration notice dismissed. Your backup remains available for restore.', 'seovault-ai' ),
			),
			'restored'               => array(
				'type' => 'success',
				'text' => __( 'Previous schema configuration restored from the verified backup. Automatic remigration is paused until you re-run migration.', 'seovault-ai' ),
			),
			'remigrated'             => array(
				'type' => 'success',
				'text' => __( 'Schema Architecture V2 migration ran again on the current configuration.', 'seovault-ai' ),
			),
			'remigrate_confirmation_required' => array(
				'type' => 'error',
				'text' => __( 'Re-run migration requires explicit confirmation.', 'seovault-ai' ),
			),
			'confirmation_required'  => array(
				'type' => 'error',
				'text' => __( 'Restore requires explicit confirmation.', 'seovault-ai' ),
			),
			'backup_missing'         => array(
				'type' => 'error',
				'text' => __( 'No migration backup was found.', 'seovault-ai' ),
			),
			'backup_corrupt'         => array(
				'type' => 'error',
				'text' => __( 'The migration backup failed checksum verification and was not restored.', 'seovault-ai' ),
			),
			'lock_contention'        => array(
				'type' => 'error',
				'text' => __( 'Another schema migration operation is in progress. Try again shortly.', 'seovault-ai' ),
			),
			'forbidden'              => array(
				'type' => 'error',
				'text' => __( 'You do not have permission to perform this action.', 'seovault-ai' ),
			),
			'nonce'                  => array(
				'type' => 'error',
				'text' => __( 'Security check failed. Please try again.', 'seovault-ai' ),
			),
		);

		return isset( $map[ $key ] ) ? $map[ $key ] : null;
	}

	/**
	 * Dismiss notice handler (capability + nonce). Backup is retained.
	 *
	 * @return void
	 */
	public static function handle_dismiss() {
		if ( ! self::current_user_can_manage() ) {
			wp_die(
				esc_html__( 'You do not have permission to dismiss this notice.', 'seovault-ai' ),
				esc_html__( 'Forbidden', 'seovault-ai' ),
				array( 'response' => 403 )
			);
		}

		check_admin_referer( self::NONCE_DISMISS );
		SchemaMigration::dismiss_notice();

		wp_safe_redirect( self::review_url( array( 'sv2_msg' => 'dismissed' ) ) );
		exit;
	}

	/**
	 * Secure restore handler (capability + nonce + confirmation + checksummed restore).
	 *
	 * @return void
	 */
	public static function handle_restore() {
		if ( ! self::current_user_can_manage() ) {
			wp_safe_redirect( self::review_url( array( 'sv2_msg' => 'forbidden' ) ) );
			exit;
		}

		if ( ! isset( $_POST['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), self::NONCE_RESTORE ) ) {
			wp_safe_redirect( self::review_url( array( 'sv2_msg' => 'nonce' ) ) );
			exit;
		}

		$confirmed = isset( $_POST['seovault_schema_v2_restore_confirm'] )
			&& '1' === sanitize_text_field( wp_unslash( $_POST['seovault_schema_v2_restore_confirm'] ) );
		$result    = SchemaMigration::restore_from_backup(
			array(
				'confirmed' => $confirmed,
			)
		);

		$msg = ! empty( $result['success'] ) ? 'restored' : (string) ( $result['error'] ?? 'backup_missing' );
		wp_safe_redirect( self::review_url( array( 'sv2_msg' => $msg ) ) );
		exit;
	}

	/**
	 * Explicit remigrate handler (capability + nonce + confirmation).
	 *
	 * Clears the post-restore auto-migration pause and runs Schema V2 migration.
	 *
	 * @return void
	 */
	public static function handle_remigrate() {
		if ( ! self::current_user_can_manage() ) {
			wp_safe_redirect( self::review_url( array( 'sv2_msg' => 'forbidden' ) ) );
			exit;
		}

		if ( ! isset( $_POST['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), self::NONCE_REMIGRATE ) ) {
			wp_safe_redirect( self::review_url( array( 'sv2_msg' => 'nonce' ) ) );
			exit;
		}

		$confirmed = isset( $_POST['seovault_schema_v2_remigrate_confirm'] )
			&& '1' === sanitize_text_field( wp_unslash( $_POST['seovault_schema_v2_remigrate_confirm'] ) );
		if ( ! $confirmed ) {
			wp_safe_redirect( self::review_url( array( 'sv2_msg' => 'remigrate_confirmation_required' ) ) );
			exit;
		}

		$result = SchemaMigration::remigrate();
		$msg    = ! empty( $result['success'] ) ? 'remigrated' : (string) ( $result['error'] ?? 'lock_contention' );
		wp_safe_redirect( self::review_url( array( 'sv2_msg' => $msg ) ) );
		exit;
	}
}
