<?php
/**
 * Plugin Name:     Radius Booking - Al-Powered Appointment & Service Booking
 * Description:     Radius Booking is an intelligent, AI-powered booking ecosystem for WordPress. Designed for Service Bookings (Salons, HVAC, Cleaning), Healthcare (Medical Clinics), Meeting and Events. Radius Booking transforms your website into a 24/7 autonomous booking engine that boosts conversion through intelligent, real-time customer interaction.
 * Plugin URI:      https://radiusbooking.co
 * Version:         1.0.16
 * Author:          RadiusTheme
 * Text Domain:     radius-booking
 * Domain Path:     /languages
 * Requires PHP:    7.4
 * Requires WP:     5.5.0
 * Namespace:       RadiusBooking
 * License:         GPLv2
 */


use RadiusTheme\RadiusBooking\Core\Api\ApiManager;
use RadiusTheme\RadiusBooking\Core\Config;
use RadiusTheme\RadiusBooking\Emails\TemplateHooks;
use RadiusTheme\RadiusBooking\Hooks\GoogleIntegrationHook;
use RadiusTheme\RadiusBooking\Integrations\GoogleCalendarMeetIntegration;

defined( 'ABSPATH' ) || exit;

/**
 * Class RadiusBooking
 *
 * Main class for the RadiusBooking plugin. Manages initialization,
 * plugin activation, deactivation, hooks, constants, and integration of
 * functional components.
 *
 * @since 1.0.0
 */
final class RadiusBooking {
	/**
	 * Plugin version.
	 *
	 * @var string
	 */
	const VERSION = '1.0.16';

	const DBVERSION = '1.2.4';

	/**
	 * Plugin slug.
	 *
	 * @var string
	 *
	 * @since 1.0.0
	 */
	const SLUG = 'radius-booking';

	/**
	 * Holds various class instances.
	 *
	 * @var array
	 *
	 * @since 1.0.0
	 */
	private $container = array();


	/**
	 * Shortcode instance
	 *
	 * @var \RadiusTheme\RadiusBooking\Shortcodes\Shortcodes
	 */
	public $shortcode;


	/**
	 * Email instance
	 *
	 * @var \RadiusTheme\RadiusBooking\Emails\EmailManager
	 */
	public $emails;

	/**
	 * Integration instance
	 *
	 * @var \RadiusTheme\RadiusBooking\Integrations\GoogleCalendarMeetIntegration
	 */
	public $integration;

	/**
	 * Constructor for the PluginName class.
	 *
	 * Sets up all the appropriate hooks and actions within our plugin.
	 *
	 * @since 1.0.0
	 */
	private function __construct() {
		require_once __DIR__ . '/vendor/autoload.php';
		require_once __DIR__ . '/vendor/woocommerce/action-scheduler/action-scheduler.php';

		$this->define_constants();

		register_activation_hook( __FILE__, array( $this, 'activate' ) );
		register_deactivation_hook( __FILE__, array( $this, 'deactivate' ) );

		add_action( 'wp_loaded', array( $this, 'flush_rewrite_rules' ) );
		$this->init_plugin();
	}

	/**
	 * Initializes the PluginBoilerplate() class.
	 *
	 * Checks for an existing PluginBoilerplate() instance
	 * and if it doesn't find one, creates it.
	 *
	 * @since 1.0.0
	 *
	 * @return RadiusBooking|bool
	 */
	public static function init() {
		static $instance = false;

		if ( ! $instance ) {
			$instance = new RadiusBooking();
		}

		return $instance;
	}

	/**
	 * Magic getter method for accessing properties.
	 *
	 * Checks if the property exists in the container array and returns its value
	 * if found. If not found in the container, attempts to access the property
	 * directly from the object.
	 *
	 * @param string $prop The name of the property being accessed.
	 *
	 * @return mixed The value of the property, if it exists.
	 */
	public function __get( $prop ) {
		if ( array_key_exists( $prop, $this->container ) ) {
			return $this->container[ $prop ];
		}

		return $this->{$prop};
	}

	/**
	 * Checks if a property is set.
	 *
	 * @param string $prop The name of the property to check.
	 *
	 * @return bool True if the property is set, false otherwise.
	 */
	public function __isset( $prop ) {
		return isset( $this->{$prop} ) || isset( $this->container[ $prop ] );
	}

	/**
	 * Define the constants.
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */
	public function define_constants() {
		define( 'RADIUS_BOOKING_VERSION', self::VERSION );
		define( 'RADIUS_BOOKING_DB_VERSION', self::DBVERSION );
		define( 'RADIUS_BOOKING_SLUG', self::SLUG );

		define( 'RADIUS_BOOKING_FILE', __FILE__ );
		define( 'RADIUS_BOOKING_DIR', plugin_dir_path( __FILE__ ) );
		define( 'RADIUS_BOOKING_PATH', dirname( RADIUS_BOOKING_FILE ) );
		define( 'RADIUS_BOOKING_INCLUDES', RADIUS_BOOKING_PATH . '/includes' );
		define( 'RADIUS_BOOKING_TEMPLATE_PATH', RADIUS_BOOKING_PATH . '/views' );
		define( 'RADIUS_BOOKING_URL', plugin_dir_url( __FILE__ ) );
		define( 'RADIUS_BOOKING_BUILD', RADIUS_BOOKING_URL . '/build' );
		define( 'RADIUS_BOOKING_ASSETS', RADIUS_BOOKING_URL . '/assets' );
		define( 'RADIUS_BOOKING_TEMPLATES_DIR', RADIUS_BOOKING_DIR . '/templates/emails/' );

		define( 'RADIUS_BOOKING_PRODUCTION', 'yes' );
		// define( 'RADIUS_BOOKING_DEV', false )
	}

	/**
	 * Load the plugin after all plugins are loaded.
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */
	public function init_plugin() {
		$this->includes();
		$this->init_hooks();

		add_action( 'init', array( '\RadiusTheme\RadiusBooking\Shortcodes\Shortcodes', 'init' ) );
		RadiusTheme\RadiusBooking\Setup\Installer::init();

		// Multisite: auto-setup tables when a new site is created.
		add_action( 'wp_insert_site', array( $this, 'on_new_site_created' ) );

		// Elementor integration — must hook early before Elementor registers widgets.
		add_action(
			'init',
			function () {
				new RadiusTheme\RadiusBooking\Elementor\ElementorManager();
			}
		);

		// Gutenberg blocks.
		new RadiusTheme\RadiusBooking\Blocks\BlockManager();
		/**
		 * Fires after the plugin is loaded.
		 *
		 * @since 1.0.0
		 */
		do_action( 'radius_booking_loaded' );
	}

	/**
	 * Activating the plugin.
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */
	public function activate( $network_wide = false ) {
		if ( is_multisite() && $network_wide ) {
			$this->network_activate();
			return;
		}

		// Run the installer to create necessary migrations.
		$this->install();

		// On multisite subsites, skip the setup wizard redirect.
		if ( is_multisite() && ! is_main_site() ) {
			return;
		}

		// Set transient for activation redirect to setup wizard.
		set_transient( RadiusTheme\RadiusBooking\Common\Keys::RADIUS_BOOKING_ACTIVATION_REDIRECT, true, 30 );
	}

	/**
	 * Run activation on every site in the network.
	 *
	 * @since 1.0.5
	 *
	 * @return void
	 */
	private function network_activate() {
		global $wpdb;

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$blog_ids = $wpdb->get_col( "SELECT blog_id FROM {$wpdb->blogs}" );

		foreach ( $blog_ids as $blog_id ) {
			switch_to_blog( $blog_id );
			$this->install();
			restore_current_blog();
		}
	}

	/**
	 * Set up plugin tables when a new site is created on a multisite network.
	 *
	 * Only runs if the plugin is network-activated.
	 *
	 * @since 1.0.5
	 *
	 * @param \WP_Site $new_site New site object.
	 *
	 * @return void
	 */
	public function on_new_site_created( $new_site ) {
		if ( ! is_plugin_active_for_network( plugin_basename( __FILE__ ) ) ) {
			return;
		}

		switch_to_blog( $new_site->blog_id );
		$this->install();
		restore_current_blog();
	}

	/**
	 * Placeholder for deactivation function.
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */
	public function deactivate( $network_wide = false ) {
		// Placeholder for deactivation logic.
		// Tables and data are intentionally preserved on deactivation.
	}

	/**
	 * Flush rewrite rules after plugin is activated.
	 *
	 * Nothing being added here yet.
	 *
	 * @since 1.0.0
	 */
	public function flush_rewrite_rules() {
		// fix rewrite rules
	}

	/**
	 * Run the installer to create necessary migrations and seeders.
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */
	private function install() {
		$installer = new RadiusTheme\RadiusBooking\Setup\Installer();
		$installer->run();
	}

	/**
	 * Include the required files.
	 *
	 * @since 0.2.0
	 *
	 * @return void
	 */
	public function includes() {
		if ( $this->is_request( 'admin' ) ) {
			$this->container['admin_menu'] = new RadiusTheme\RadiusBooking\Admin\Menu();
		}
		$this->container['assets']   = new RadiusTheme\RadiusBooking\Assets\LoadAssets();
		$this->container['rest_api'] = new ApiManager();

		include_once plugin_dir_path( __FILE__ ) . 'includes/Utility/core-functions.php';
		include_once plugin_dir_path( __FILE__ ) . 'includes/Utility/country-helper.php';
		include_once plugin_dir_path( __FILE__ ) . 'includes/Utility/payment-gateway-currency-support.php';
		include_once plugin_dir_path( __FILE__ ) . 'includes/Utility/template-functions.php';
	}

	/**
	 * Initialize the hooks.
	 *
	 * @since 0.2.0
	 *
	 * @return void
	 */
	public function init_hooks() {
		// Init classes
		add_action( 'init', array( $this, 'init_classes' ) );

		// Add the plugin page links
		add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'plugin_action_links' ) );

		add_action( 'plugins_loaded', array( $this, 'loaded_boostrap' ) );
	}

	/**
	 * Load the bootstrap configuration.
	 *
	 * @return void
	 */
	public function loaded_boostrap() {
		new Config();
	}


	/**
	 * Instantiate the required classes.
	 *
	 * @since 0.2.0
	 *
	 * @return void
	 */
	public function init_classes() {
		// Init necessary hooks
		new RadiusTheme\RadiusBooking\Hooks\Common();
		new GoogleIntegrationHook();
		$this->integration = new GoogleCalendarMeetIntegration();
		new RadiusTheme\RadiusBooking\Integrations\ClassifiedListing\ClassifiedListingIntegration();
		do_action( 'rtrb_register_pro_integrations' );
		$this->shortcode = new RadiusTheme\RadiusBooking\Shortcodes\Shortcodes();
		$this->emails = new \RadiusTheme\RadiusBooking\Emails\EmailManager();
		new \RadiusTheme\RadiusBooking\Services\ReminderService();
		$template_hooks = TemplateHooks::init();
		RadiusTheme\RadiusBooking\Ajax\Auth::init();
		$early_bird_notice = new RadiusTheme\RadiusBooking\Admin\Notices\EarlyBirdNotice();
		$early_bird_notice->init();

	}

	/**
	 * What type of request is this.
	 *
	 * @since 0.2.0
	 *
	 * @param string $type admin, ajax, cron or frontend
	 *
	 * @return bool
	 */
	private function is_request( $type ) {
		switch ( $type ) {
			case 'admin':
				return is_admin();

			case 'ajax':
				return defined( 'DOING_AJAX' );

			case 'rest':
				return defined( 'REST_REQUEST' );

			case 'cron':
				return defined( 'DOING_CRON' );

			case 'frontend':
				return ( ! is_admin() || defined( 'DOING_AJAX' ) ) && ! defined( 'DOING_CRON' );
		}
	}

	/**
	 * Adds custom action links to the plugin in the plugins list.
	 *
	 * @param array $links An array of existing action links for the plugin.
	 *
	 * @return array Modified array of action links with added custom links.
	 */
	public function plugin_action_links( $links ) {
		$links[] = '<a href="' . admin_url( 'admin.php?page=radius-booking#/settings' ) . '">' . __( 'Settings', 'radius-booking' ) . '</a>';
		$links[] = '<a href="https://radiusbooking.co/docs/" target="_blank">' . __( 'Documentation', 'radius-booking' ) . '</a>';

		return $links;
	}
}



/**
 * Initialize the main plugin.
 *
 * @since 1.0.0
 *
 * @return \RadiusBooking|bool
 */
function radius_booking() { //phpcs:ignore
	return RadiusBooking::init();
}
radius_booking();

if ( ! function_exists( 'radius_table_prefix' ) ) {
	/**
	 * Retrieves the table prefix for radius booking tables.
	 *
	 * This function constructs the table prefix using the global `$wpdb` object and appends
	 * the default 'radius_booking_' suffix. If a custom prefix is defined in the constant
	 * `RADIUS_BOOKING_TABLE_PREFIX`, it overrides the default prefix.
	 *
	 * @return string The constructed or overridden table prefix for radius booking tables.
	 * @global wpdb $wpdb WordPress database access abstraction object.
	 */
	function radius_table_prefix() {
		global $wpdb;

		$prefix = $wpdb->prefix . 'radius_booking_';
		if ( defined( 'RADIUS_BOOKING_TABLE_PREFIX' ) && RADIUS_BOOKING_TABLE_PREFIX ) {
			$prefix = RADIUS_BOOKING_TABLE_PREFIX;
		}

		return $prefix;
	}
}


/**
 * Get the class name of an object without the namespace.
 */
if ( ! function_exists( 'rtrb_class_basename' ) ) {
	/**
	 * Retrieve the class basename from a fully qualified class name or object.
	 *
	 * @param object|string $class The object instance or the fully qualified class name.
	 *
	 * @return string The basename of the class.
	 */
	function rtrb_class_basename( $class ): string {
		if ( is_object( $class ) ) {
			$class = get_class( $class );
		}
		return basename( str_replace( '\\', '/', $class ) );
	}
}
/**
 *  Check if WP-CLI is available and register commands.
 */
if ( defined( 'WP_CLI' ) && WP_CLI ) {
	$command_registry = new \RadiusTheme\RadiusBooking\Core\CommandRegistry();
	$command_registry->init();
}