<?php
/**
 * Runs a regression check automatically after any update completes, and stores
 * the latest report for display.
 *
 * @package UpdateGuardian
 */

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

/**
 * Hooks the WordPress upgrade lifecycle and persists the last report.
 */
class Upguard_Monitor {

	const OPT_LAST_REPORT = 'upguard_last_report';

	/**
	 * @var Upguard_Client
	 */
	private $client;

	/**
	 * @param Upguard_Client $client Detection API client.
	 */
	public function __construct( Upguard_Client $client ) {
		$this->client = $client;
	}

	/**
	 * Register hooks.
	 */
	public function hooks() {
		// Fires after plugin, theme, or core updates finish.
		add_action( 'upgrader_process_complete', array( $this, 'after_update' ), 20 );
	}

	/**
	 * After an update completes, compare against the baseline and store the result.
	 */
	public function after_update() {
		$report = $this->client->compare();
		$this->store_report( $report );
	}

	/**
	 * Persist a report (or error) as the latest result, timestamped.
	 *
	 * @param array|WP_Error $report Report from the API.
	 */
	public function store_report( $report ) {
		if ( is_wp_error( $report ) ) {
			update_option(
				self::OPT_LAST_REPORT,
				array(
					'time'  => time(),
					'error' => $report->get_error_message(),
				)
			);
			return;
		}

		// Sanitize the remote report before persisting it.
		$pages = array();
		if ( isset( $report['pages'] ) && is_array( $report['pages'] ) ) {
			foreach ( $report['pages'] as $page ) {
				$problems = array();
				if ( isset( $page['problems'] ) && is_array( $page['problems'] ) ) {
					foreach ( $page['problems'] as $problem ) {
						$problems[] = array(
							'type'   => sanitize_key( isset( $problem['type'] ) ? $problem['type'] : '' ),
							'detail' => sanitize_text_field( isset( $problem['detail'] ) ? $problem['detail'] : '' ),
						);
					}
				}
				$pages[] = array(
					'path'     => sanitize_text_field( isset( $page['path'] ) ? $page['path'] : '' ),
					'ok'       => ! empty( $page['ok'] ),
					'problems' => $problems,
				);
			}
		}

		update_option(
			self::OPT_LAST_REPORT,
			array(
				'time'        => time(),
				'regressions' => isset( $report['regressions'] ) ? (int) $report['regressions'] : 0,
				'pages'       => $pages,
			)
		);
	}

	/**
	 * @return array|false The last stored report, or false if none.
	 */
	public static function last_report() {
		return get_option( self::OPT_LAST_REPORT, false );
	}
}
