<?php
/**
 * RadiusBooking API Route Registrar
 *
 * This class is responsible for registering API routes dynamically with the WordPress REST API.
 * It supports CRUD operations and allows for middleware to be applied globally or per route.
 *
 * @package RadiusTheme\RadiusBooking\Core\Api\Routes
 */

namespace RadiusTheme\RadiusBooking\Setup;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}

use RadiusTheme\RadiusBooking\Common\Keys;
use RadiusTheme\RadiusBooking\Databases\DatabaseManager;
use RadiusTheme\RadiusBooking\Helpers\SettingsHelper;
use RadiusTheme\RadiusBooking\Setup\PageInstaller;

/**
 * Installer class for setting up the Radius Booking plugin.
 *
 * This class handles the installation process, including adding version information,
 * registering table names, and creating necessary database tables.
 *
 * @since 1.0.0
 */
class Installer {

//	private static $db_updates = array(
//		'1.0.1' => array(
//			'radius_booking_102_service_add_column_table',
//		)
//	);

	/**
	 * Init the install class.
	 *
	 * @since 1.0.0
	 */
	public static function init() {
		add_action( 'admin_init', array( __CLASS__, 'activation_redirect' ), 1 );
		add_action( 'admin_init', array( __CLASS__, 'update' ), 5 );
	}

	/**
	 * Redirect to setup wizard after first activation.
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */
	public static function activation_redirect() {
		if ( ! get_transient( Keys::RADIUS_BOOKING_ACTIVATION_REDIRECT ) ) {
			return;
		}

		delete_transient( Keys::RADIUS_BOOKING_ACTIVATION_REDIRECT );

		// Don't redirect if activating from network, bulk, WP-CLI, or multisite subsites.
		if ( is_network_admin() || isset( $_GET['activate-multi'] ) || ( defined( 'WP_CLI' ) && WP_CLI ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			return;
		}

		if ( is_multisite() && ! is_main_site() ) {
			return;
		}

		wp_safe_redirect( admin_url( 'admin.php?page=radius-booking#/setup-wizard' ) );
		exit;
	}

	public static function update() {
		// Upgrade guard: existing installs should not be locked by setup wizard.
		if ( false === get_option( Keys::RADIUS_BOOKING_SETUP_COMPLETED ) ) {
			$installed = get_option( Keys::RADIUS_BOOKING_INSTALLED );
			if ( $installed ) {
				update_option( Keys::RADIUS_BOOKING_SETUP_COMPLETED, true );
			}
		}

		$current_version = get_option( Keys::RADIUS_BOOKING_DB_VERSION, '0' );
		if ( version_compare( $current_version, RADIUS_BOOKING_DB_VERSION, '<' ) ) {
			$installer = new self();
			$installer->run();
		}
	}
	/**
	 * Run the installer.
	 *
	 * @since 1.0.0
	 */
	public function run() {
		// Create tables first, then update version so a failed migration can retry.
		$this->create_tables();
		$this->backfill_payment_commission_snapshots();
		$this->add_version();

		// Create any pages added in newer versions (meeting, event, etc.).
		PageInstaller::create_missing_pages();
	}

	/**
	 * Stamp the current commission setting onto every paid/partial payment that
	 * doesn't yet have a snapshot. Runs once on upgrade — subsequent payments
	 * snapshot themselves via the Payment model's onSaving hook.
	 *
	 * @return void
	 */
	private function backfill_payment_commission_snapshots(): void {
		global $wpdb;
		$table = $wpdb->prefix . 'radius_booking_payments';

		// Bail if the column wasn't added (e.g. migration didn't run yet).
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
		$col_check = $wpdb->get_var( "SHOW COLUMNS FROM `{$table}` LIKE 'commission_type'" );
		if ( ! $col_check ) {
			return;
		}

		$settings = SettingsHelper::get_setting( 'payout' );
		if ( ! is_array( $settings ) || empty( $settings['enabled'] ) ) {
			return;
		}
		$rate = (float) ( $settings['commissionRate'] ?? 0 );
		$type = $settings['commissionType'] ?? 'percentage';

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
		$wpdb->query(
			$wpdb->prepare(
				"UPDATE `{$table}` SET commission_rate = %f, commission_type = %s
				 WHERE status IN ('paid', 'partial_payment') AND commission_type IS NULL",
				$rate,
				$type
			)
		);
	}


	/**
	 * Add time and version on DB.
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */
	public function add_version(): void {
		$installed = get_option( Keys::RADIUS_BOOKING_INSTALLED );
		if ( ! $installed ) {
			update_option( Keys::RADIUS_BOOKING_INSTALLED, time() );

			// On multisite subsites, auto-complete setup wizard so it doesn't
			// block the admin on every subsite. Only the main site shows the wizard.
			if ( is_multisite() && ! is_main_site() ) {
				update_option( Keys::RADIUS_BOOKING_SETUP_COMPLETED, true );
			} else {
				// Mark setup as not completed for first-time installs.
				add_option( Keys::RADIUS_BOOKING_SETUP_COMPLETED, false );
			}

			// Create default booking pages.
			PageInstaller::create_pages();
		}
		self::maybe_update_db_version();
		update_option( Keys::RADIUS_BOOKING_VERSION, RADIUS_BOOKING_VERSION );
	}

	/**
	 * See if we need to show or run database updates during install.
	 *
	 * @since 1.0.0
	 */
	public static function maybe_update_db_version() {
		self::update_db_version();
	}

	/**
	 * Update DB version to current.
	 *
	 * @param string|null $version
	 * @since 1.0.0
	 */
	public static function update_db_version( $version = null ) {
		update_option( Keys::RADIUS_BOOKING_DB_VERSION, is_null( $version ) ? RADIUS_BOOKING_DB_VERSION : $version );
	}


	/**
	 * Create necessary database tables.
	 *
	 * @since JOB_PLACE_
	 *
	 * @return void
	 */
	public function create_tables() {
		if ( ! current_user_can( 'activate_plugins' ) ) {
			return;
		}

		if ( ! function_exists( 'dbDelta' ) ) {
			require_once ABSPATH . 'wp-admin/includes/upgrade.php';
		}

		// Clear old migration records so renamed tables re-run cleanly.
		$this->clear_old_migration_records();

		// Run the database table migrations.
		DatabaseManager::migrate();
		// Flush rewrite rules to ensure new tables are recognized.
	}

	/**
	 * Remove migration records from previous DB versions so migrations re-run cleanly.
	 *
	 * @return void
	 */
	private function clear_old_migration_records() {
		global $wpdb;

		$table = $wpdb->prefix . 'radius_booking_migrations';

		// Bail if the migrations table doesn't exist yet (fresh install).
		$exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) ); //phpcs:ignore
		if ( empty( $exists ) ) {
			return;
		}

		$current_prefix = RADIUS_BOOKING_DB_VERSION . '_';

		// Delete records that don't match the current DB version prefix.
		$wpdb->query( //phpcs:ignore
			$wpdb->prepare(
				"DELETE FROM `{$table}` WHERE migration NOT LIKE %s",
				$current_prefix . '%'
			)
		);

		wp_cache_delete( 'radius_booking_executed_migrations' );
	}
}
