<?php
/**
 * Armed baselines: snapshot every monitored page on demand, run your updates,
 * then compare the live output against that snapshot.
 *
 * This is the same record-and-diff engine the scheduled checks use, driven by
 * hand instead of by cron. It is part of the free plugin.
 *
 * @package SEO_Flight_Recorder
 */

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

/**
 * Class SFRec_Baseline
 */
class SFRec_Baseline {

	/**
	 * Wire hooks.
	 */
	public static function init() {
		add_action( 'sfrec_flight_log_actions', array( __CLASS__, 'render_controls' ) );
		add_action( 'admin_post_sfrec_arm_baseline', array( __CLASS__, 'handle_arm' ) );
		add_action( 'admin_post_sfrec_compare_baseline', array( __CLASS__, 'handle_compare' ) );
	}

	/**
	 * How many pages currently hold an armed baseline.
	 *
	 * @return int
	 */
	public static function armed_count() {
		global $wpdb;
		return (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}sfrec_snapshots WHERE kind = 'baseline'" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- own table.
	}

	/**
	 * The arm/compare controls on the Flight Log headline row.
	 */
	public static function render_controls() {
		$armed = self::armed_count();
		?>
		<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="sfrec-inline-form">
			<input type="hidden" name="action" value="sfrec_arm_baseline" />
			<?php wp_nonce_field( 'sfrec_arm_baseline' ); ?>
			<button type="submit" class="button"><?php esc_html_e( 'Arm baseline (before an update)', 'buildsbyluke-seo-flight-recorder' ); ?></button>
		</form>
		<?php if ( $armed > 0 ) : ?>
			<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="sfrec-inline-form">
				<input type="hidden" name="action" value="sfrec_compare_baseline" />
				<?php wp_nonce_field( 'sfrec_compare_baseline' ); ?>
				<button type="submit" class="button"><?php esc_html_e( 'Compare against armed baseline', 'buildsbyluke-seo-flight-recorder' ); ?></button>
			</form>
			<?php
		endif;
	}

	/**
	 * Snapshot every monitored page into the 'baseline' slot.
	 */
	public static function handle_arm() {
		global $wpdb;

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'Insufficient permissions.', 'buildsbyluke-seo-flight-recorder' ) );
		}
		check_admin_referer( 'sfrec_arm_baseline' );

		$settings = get_option( 'sfrec_settings', array() );

		foreach ( SFRec_Scanner::pages() as $page ) {
			$result = SFRec_Fetcher::fetch( $page->url, array( 'cache_bypass' => ! empty( $settings['cache_bypass'] ) ) );
			if ( is_wp_error( $result ) ) {
				continue;
			}
			$fields = SFRec_Parser::extract( $result['body'], $result['headers'], $result['status'], $result['redirect_to'] );

			$wpdb->delete( // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- own table.
				$wpdb->prefix . 'sfrec_snapshots',
				array(
					'page_id' => (int) $page->id,
					'kind'    => 'baseline',
				),
				array( '%d', '%s' )
			);
			$wpdb->insert( // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- own table.
				$wpdb->prefix . 'sfrec_snapshots',
				array(
					'page_id'     => (int) $page->id,
					'kind'        => 'baseline',
					'fields'      => wp_json_encode( $fields ),
					'fields_hash' => SFRec_Parser::hash_fields( $fields ),
					'captured_at' => gmdate( 'Y-m-d H:i:s' ),
				),
				array( '%d', '%s', '%s', '%s', '%s' )
			);
		}

		wp_safe_redirect( add_query_arg( 'sfrec_msg', 'baseline-armed', admin_url( 'admin.php?page=seo-flight-recorder' ) ) );
		exit;
	}

	/**
	 * Compare live output against the armed baseline, logging any differences.
	 */
	public static function handle_compare() {
		global $wpdb;

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'Insufficient permissions.', 'buildsbyluke-seo-flight-recorder' ) );
		}
		check_admin_referer( 'sfrec_compare_baseline' );

		$settings = get_option( 'sfrec_settings', array() );
		$found    = 0;

		foreach ( SFRec_Scanner::pages() as $page ) {
			$baseline = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}sfrec_snapshots WHERE page_id = %d AND kind = 'baseline'", (int) $page->id ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- own table.
			if ( ! $baseline ) {
				continue;
			}
			$result = SFRec_Fetcher::fetch( $page->url, array( 'cache_bypass' => ! empty( $settings['cache_bypass'] ) ) );
			if ( is_wp_error( $result ) ) {
				continue;
			}
			$before = json_decode( (string) $baseline->fields, true );
			if ( ! is_array( $before ) ) {
				continue;
			}
			$after = SFRec_Parser::extract( $result['body'], $result['headers'], $result['status'], $result['redirect_to'] );
			$since = strtotime( $baseline->captured_at . ' UTC' );
			$diffs = SFRec_Differ::diff( array_merge( SFRec_Parser::extract( '' ), $before ), $after, SFRec_Events::since( $since ? $since : 0 ), (int) $page->post_id );

			foreach ( $diffs as $diff ) {
				if ( SFRec_Scanner::insert_change( (int) $page->id, $diff['field'], $diff['before'], $diff['after'], $diff['severity'], $diff['classification'], $diff['suspects'] ) ) {
					$found++;
				}
			}
		}

		wp_safe_redirect(
			add_query_arg(
				array(
					'sfrec_msg'   => 'baseline-compared',
					'sfrec_found' => $found,
				),
				admin_url( 'admin.php?page=seo-flight-recorder' )
			)
		);
		exit;
	}
}
