<?php
/**
 * Install/schema/defaults.
 *
 * @package SEO_Flight_Recorder
 */

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

/**
 * Class SFRec_Install
 */
class SFRec_Install {

	const DB_VERSION = '2';

	/**
	 * Activate.
	 */
	public static function activate() {
		self::create_tables();
		self::set_defaults();
		self::seed_pages();
		update_option( 'sfrec_db_version', self::DB_VERSION );

		SFRec_Scanner::ensure_schedule();
	}

	/**
	 * Deactivate: clear schedules (data stays; uninstall removes it).
	 */
	public static function deactivate() {
		foreach ( self::cron_hooks() as $sfrec_hook ) {
			wp_clear_scheduled_hook( $sfrec_hook );
		}
	}

	/**
	 * Every cron hook this plugin has ever registered, including the pre-1.0.1
	 * split daily/hourly hooks that the single `sfrec_scheduled_check` event
	 * replaced. Listed here so deactivation and uninstall both clear the lot.
	 *
	 * @return string[]
	 */
	public static function cron_hooks() {
		return array(
			'sfrec_scheduled_check',
			'sfrec_post_update_check',
			'sfrec_run_batch',
			'sfrec_daily_check',
			'sfrec_hourly_check',
			'sfrec_pro_weekly_digest',
		);
	}

	/**
	 * Upgrade routine.
	 */
	public static function maybe_upgrade() {
		if ( (string) get_option( 'sfrec_db_version' ) === self::DB_VERSION ) {
			return;
		}

		self::create_tables();
		self::migrate_check_frequency();
		update_option( 'sfrec_db_version', self::DB_VERSION );
	}

	/**
	 * 1.0.0 stored a `daily_check` on/off flag and drove a `sfrec_daily_check`
	 * cron event; 1.0.1 replaced both with a `check_frequency` choice on one
	 * `sfrec_scheduled_check` event. Carry the old preference across and retire
	 * the old events.
	 */
	private static function migrate_check_frequency() {
		$settings = get_option( 'sfrec_settings', array() );
		if ( ! is_array( $settings ) ) {
			return;
		}

		if ( ! isset( $settings['check_frequency'] ) ) {
			$settings['check_frequency'] = empty( $settings['daily_check'] ) && isset( $settings['daily_check'] ) ? 'off' : 'daily';
			unset( $settings['daily_check'] );
			update_option( 'sfrec_settings', $settings );
		}

		wp_clear_scheduled_hook( 'sfrec_daily_check' );
		wp_clear_scheduled_hook( 'sfrec_hourly_check' );
		SFRec_Scanner::ensure_schedule();
	}

	/**
	 * Tables. `snapshots` holds the last-known-good field set per page (one row
	 * per page, plus an optional armed-baseline row); `changes` is the flight
	 * log itself.
	 */
	public static function create_tables() {
		global $wpdb;
		require_once ABSPATH . 'wp-admin/includes/upgrade.php';
		$charset = $wpdb->get_charset_collate();

		dbDelta(
			"CREATE TABLE {$wpdb->prefix}sfrec_pages (
				id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
				url TEXT NOT NULL,
				url_hash CHAR(32) NOT NULL,
				label VARCHAR(191) NOT NULL DEFAULT '',
				post_id BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
				is_active TINYINT(1) NOT NULL DEFAULT 1,
				added_at DATETIME NOT NULL,
				PRIMARY KEY  (id),
				UNIQUE KEY url_hash (url_hash)
			) $charset;"
		);

		dbDelta(
			"CREATE TABLE {$wpdb->prefix}sfrec_snapshots (
				id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
				page_id BIGINT(20) UNSIGNED NOT NULL,
				kind VARCHAR(12) NOT NULL DEFAULT 'current',
				fields LONGTEXT NULL,
				fields_hash CHAR(32) NOT NULL DEFAULT '',
				captured_at DATETIME NOT NULL,
				PRIMARY KEY  (id),
				UNIQUE KEY page_kind (page_id, kind)
			) $charset;"
		);

		dbDelta(
			"CREATE TABLE {$wpdb->prefix}sfrec_changes (
				id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
				page_id BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
				field VARCHAR(48) NOT NULL,
				before_val TEXT NULL,
				after_val TEXT NULL,
				severity VARCHAR(10) NOT NULL DEFAULT 'info',
				classification VARCHAR(24) NOT NULL DEFAULT 'unexplained',
				suspects LONGTEXT NULL,
				detected_at DATETIME NOT NULL,
				status VARCHAR(12) NOT NULL DEFAULT 'new',
				note TEXT NULL,
				PRIMARY KEY  (id),
				KEY page_id (page_id),
				KEY severity (severity),
				KEY detected_at (detected_at)
			) $charset;"
		);
	}

	/**
	 * Defaults.
	 */
	public static function set_defaults() {
		if ( false !== get_option( 'sfrec_settings', false ) ) {
			return;
		}
		update_option(
			'sfrec_settings',
			array(
				'alert_email'       => get_option( 'admin_email' ),
				'email_alerts'      => 1,
				'email_threshold'   => 'warning',
				'email_all_clear'   => 1,
				'check_frequency'   => 'daily',
				'post_update_check' => 1,
				'cache_bypass'      => 0,
				'retention_days'    => 0,
			)
		);
		add_option( 'sfrec_events', array(), '', 'no' );
		add_option(
			'sfrec_state',
			array(
				'last_check'     => 0,
				'loopback_ok'    => null,
				'loopback_error' => '',
				'sitemap_url'    => '',
				'sitemap_count'  => 0,
				'robots_hash'    => '',
				'robots_excerpt' => '',
			),
			'',
			'no'
		);
	}

	/**
	 * Seed the monitored-pages list with the front page so the first check has
	 * something meaningful to record without any configuration.
	 */
	public static function seed_pages() {
		global $wpdb;
		$sfrec_count = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}sfrec_pages" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- own table, activation-time seed check.
		if ( $sfrec_count > 0 ) {
			return;
		}
		$sfrec_home = home_url( '/' );
		$wpdb->insert( // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- own table.
			$wpdb->prefix . 'sfrec_pages',
			array(
				'url'      => $sfrec_home,
				'url_hash' => md5( $sfrec_home ),
				'label'    => __( 'Front page', 'buildsbyluke-seo-flight-recorder' ),
				'post_id'  => (int) get_option( 'page_on_front' ),
				'is_active' => 1,
				'added_at' => gmdate( 'Y-m-d H:i:s' ),
			),
			array( '%s', '%s', '%s', '%d', '%d', '%s' )
		);
	}
}
