<?php

/**
 * FlexOrder Cross-Promotion Manager
 * Detects the Order Sync with Google Sheets plugin and shows a contextual
 * promotional modal after the user completes their first archive operation.
 *
 * @since 1.13.0
 * @package ArchiveMaster
 */

// Namespace.
namespace ARCHM\Admin;

// Exit if accessed directly.
defined( 'ABSPATH' ) || exit( 1 );

if ( ! class_exists( __NAMESPACE__ . '\FlexOrderPromotion' ) ) {

	/**
	 * FlexOrder Cross-Promotion Manager
	 *
	 * @since 1.13.0
	 */
	class FlexOrderPromotion {

		/**
		 * FlexOrder plugin slug (folder/file).
		 *
		 * @var string
		 */
		const FLEXORDER_PLUGIN = 'order-sync-with-google-sheets-for-woocommerce/order-sync-with-google-sheets-for-woocommerce.php';

		/**
		 * WP option — set to true when the user permanently dismisses the modal.
		 *
		 * @var string
		 */
		const OPTION_DISMISSED = 'archm_flexorder_modal_dismissed';

		/**
		 * WP option — set to true when the user permanently dismisses the banner.
		 *
		 * @var string
		 */
		const OPTION_BANNER_DISMISSED = 'archm_flexorder_banner_dismissed';

		/**
		 * WP option — stores the timestamp when the user first became eligible for the banner.
		 *
		 * @var string
		 */
		const OPTION_BANNER_ELIGIBLE_AT = 'archm_flexorder_banner_eligible_at';

		/**
		 * WP option — set to true when the user permanently dismisses the dashboard modal.
		 *
		 * @var string
		 */
		const OPTION_DASHBOARD_DISMISSED = 'archm_flexorder_dashboard_modal_dismissed';

		/**
		 * WP option — stores the timestamp when the user first became eligible for the dashboard modal.
		 *
		 * @var string
		 */
		const OPTION_DASHBOARD_ELIGIBLE_AT = 'archm_flexorder_dashboard_modal_eligible_at';

		/**
		 * WP option — set to true when the user performs their first archive operation.
		 *
		 * @var string
		 */
		const OPTION_FIRST_ARCHIVE_PERFORMED = 'archm_first_archive_performed';

		/**
		 * REST API namespace (shared with AdminRest).
		 *
		 * @var string
		 */
		protected $namespace = 'archm/v1';

		/**
		 * Class constructor — registers all WordPress hooks.
		 */
		public function __construct() {
			add_action( 'rest_api_init', [ $this, 'register_routes' ] );

			// Hook into archive events to track the first-time archive operation.
			add_action( 'archm_order_archived', [ __CLASS__, 'mark_first_archive_performed' ] );
			add_action( 'archm_orders_bulk_archived', [ __CLASS__, 'mark_first_archive_performed' ] );
		}

		/**
		 * Register REST API routes for the promo modal.
		 *
		 * @return void
		 */
		public function register_routes() {
			// GET  — returns current modal visibility data.
			register_rest_route(
				$this->namespace,
				'/flexorder-promo-data',
				[
					'methods'             => \WP_REST_Server::READABLE,
					'callback'            => [ $this, 'get_promo_data' ],
					'permission_callback' => [ $this, 'check_admin_permissions' ],
				]
			);

			// POST — persists modal dismissal.
			register_rest_route(
				$this->namespace,
				'/flexorder-dismiss-modal',
				[
					'methods'             => \WP_REST_Server::EDITABLE,
					'callback'            => [ $this, 'dismiss_modal' ],
					'permission_callback' => [ $this, 'check_admin_permissions' ],
				]
			);

			// POST — persists banner dismissal.
			register_rest_route(
				$this->namespace,
				'/flexorder-dismiss-banner',
				[
					'methods'             => \WP_REST_Server::EDITABLE,
					'callback'            => [ $this, 'dismiss_banner' ],
					'permission_callback' => [ $this, 'check_admin_permissions' ],
				]
			);

			// POST — persists dashboard modal dismissal.
			register_rest_route(
				$this->namespace,
				'/flexorder-dismiss-dashboard-modal',
				[
					'methods'             => \WP_REST_Server::EDITABLE,
					'callback'            => [ $this, 'dismiss_dashboard_modal' ],
					'permission_callback' => [ $this, 'check_admin_permissions' ],
				]
			);

			// POST — triggers automatic installation and activation of FlexOrder.
			register_rest_route(
				$this->namespace,
				'/flexorder-install-plugin',
				[
					'methods'             => \WP_REST_Server::EDITABLE,
					'callback'            => [ $this, 'install_and_activate_plugin' ],
					'permission_callback' => [ $this, 'check_admin_permissions' ],
				]
			);
		}

		/**
		 * REST permission callback — requires manage_options and a valid nonce.
		 *
		 * @param \WP_REST_Request $request Incoming request.
		 * @return bool|\WP_Error
		 */
		public function check_admin_permissions( \WP_REST_Request $request ) {
			$nonce = $request->get_header( 'X-WP-Nonce' );

			if ( ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
				return new \WP_Error(
					'rest_forbidden',
					__( 'Invalid nonce.', 'archive-master' ),
					[ 'status' => 403 ]
				);
			}

			if ( ! current_user_can( 'manage_options' ) ) {
				return new \WP_Error(
					'rest_forbidden',
					__( 'You do not have permission to do this.', 'archive-master' ),
					[ 'status' => 403 ]
				);
			}

			return true;
		}

		/**
		 * REST callback — returns current modal data as a JSON response.
		 *
		 * @return \WP_REST_Response
		 */
		public function get_promo_data() {
			return rest_ensure_response(
				[
					'success' => true,
					'data'    => [
						'show_modal'          => $this->should_show_modal(),
						'is_flexorder_active' => $this->is_flexorder_active(),
						'active_order_count'  => $this->get_active_order_count(),
					],
				]
			);
		}

		/**
		 * REST callback — saves the dismissal flag and clears the cached count.
		 *
		 * @return \WP_REST_Response
		 */
		public function dismiss_modal() {
			// Persist — not autoloaded since it's rarely needed on every page.
			update_option( self::OPTION_DISMISSED, true, false );

			return rest_ensure_response(
				[
					'success' => true,
					'message' => __( 'Modal dismissed.', 'archive-master' ),
				]
			);
		}

		/**
		 * REST callback — saves the banner dismissal flag.
		 *
		 * @return \WP_REST_Response
		 */
		public function dismiss_banner() {
			update_option( self::OPTION_BANNER_DISMISSED, true, false );

			return rest_ensure_response(
				[
					'success' => true,
					'message' => __( 'Banner dismissed.', 'archive-master' ),
				]
			);
		}

		/**
		 * REST callback — saves the dashboard modal dismissal flag.
		 *
		 * @return \WP_REST_Response
		 */
		public function dismiss_dashboard_modal() {
			update_option( self::OPTION_DASHBOARD_DISMISSED, true, false );

			return rest_ensure_response(
				[
					'success' => true,
					'message' => __( 'Dashboard modal dismissed.', 'archive-master' ),
				]
			);
		}

		/**
		 * REST callback — handles automatic installation and activation of FlexOrder.
		 *
		 * @return \WP_REST_Response
		 */
		public function install_and_activate_plugin() {
			// Ensure current user is allowed to manage plugins.
			if ( ! current_user_can( 'install_plugins' ) || ! current_user_can( 'activate_plugins' ) ) {
				return new \WP_Error(
					'rest_forbidden',
					__( 'You do not have permission to install plugins.', 'archive-master' ),
					[ 'status' => 403 ]
				);
			}

			$slug   = 'order-sync-with-google-sheets-for-woocommerce';
			$plugin = self::FLEXORDER_PLUGIN;

			// 1. Check if already active.
			if ( $this->is_flexorder_active() ) {
				return rest_ensure_response(
					[
						'success' => true,
						'message' => __( 'FlexOrder is already installed and active.', 'archive-master' ),
					]
				);
			}

			// 2. Check if installed but inactive.
			$installed_plugins = get_plugins();
			if ( isset( $installed_plugins[ $plugin ] ) ) {
				$result = activate_plugin( $plugin );
				if ( is_wp_error( $result ) ) {
					return $result;
				}

				return rest_ensure_response(
					[
						'success' => true,
						'message' => __( 'FlexOrder activated successfully.', 'archive-master' ),
					]
				);
			}

			// 3. Not installed — perform installation.
			require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
			require_once ABSPATH . 'wp-admin/includes/file.php';
			require_once ABSPATH . 'wp-admin/includes/misc.php';
			require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';

			$api = plugins_api(
				'plugin_information',
				[
					'slug'   => $slug,
					'fields' => [
						'sections' => false,
					],
				]
			);

			if ( is_wp_error( $api ) ) {
				return $api;
			}

			$upgrader = new \Plugin_Upgrader( new \Automatic_Upgrader_Skin() );
			$result   = $upgrader->install( $api->download_link );

			if ( is_wp_error( $result ) ) {
				return $result;
			}

			if ( true !== $result ) {
				return new \WP_Error(
					'install_failed',
					__( 'Plugin installation failed.', 'archive-master' )
				);
			}

			// 4. Activate after installation.
			$result = activate_plugin( $plugin );
			if ( is_wp_error( $result ) ) {
				return $result;
			}

			return rest_ensure_response(
				[
					'success' => true,
					'message' => __( 'FlexOrder installed and activated successfully.', 'archive-master' ),
				]
			);
		}

		/**
		 * Returns the full promo data array for use in wp_localize_script().
		 * Called statically from Assets.php — does not register any hooks.
		 *
		 * @return array
		 */
		public static function get_localize_data() {
			// If not FlexOrder active and no eligible_at yet, set it now.
			if ( ! self::is_flexorder_active_static() ) {
				if ( ! get_option( self::OPTION_BANNER_ELIGIBLE_AT ) ) {
					update_option( self::OPTION_BANNER_ELIGIBLE_AT, time(), false );
				}
				if ( ! get_option( self::OPTION_DASHBOARD_ELIGIBLE_AT ) ) {
					update_option( self::OPTION_DASHBOARD_ELIGIBLE_AT, time(), false );
				}
			}

			return [
				'show_modal'            => self::should_show_modal_static(),
				'show_modal_auto'       => self::should_show_modal_auto_static(),
				'show_banner'           => self::should_show_banner_static(),
				'show_dashboard_modal'  => self::should_show_dashboard_modal_static(),
				'show_permanent_banner' => ! self::is_flexorder_installed_static(),
				'is_active'             => self::is_flexorder_active_static(),
				'active_orders'         => self::get_active_order_count_static(),
				'install_url'           => self_admin_url( 'plugin-install.php?s=FlexOrder&tab=search&type=term' ),
				'plugin_url'            => esc_url( 'https://lnk.wppool.dev/gWV8px3' ),
			];
		}

		/**
		 * Determines whether the dashboard modal should be shown.
		 *
		 * @return bool
		 */
		public static function should_show_dashboard_modal_static() {
			if ( self::is_flexorder_installed_static() ) {
				return false;
			}

			if ( get_option( self::OPTION_DASHBOARD_DISMISSED, false ) ) {
				return false;
			}

			$eligible_at = get_option( self::OPTION_DASHBOARD_ELIGIBLE_AT );
			if ( ! $eligible_at ) {
				return false;
			}

			// Show after 15 days for production.
			$delay = 1296000;
			if ( time() < ( (int) $eligible_at + $delay ) ) {
				return false;
			}

			if ( self::get_active_order_count_static() < 10 ) {
				return false;
			}

			return true;
		}

		/**
		 * Determines whether the banner should be shown (static version).
		 *
		 * @return bool
		 */
		public static function should_show_banner_static() {
			if ( self::is_flexorder_installed_static() ) {
				return false;
			}

			if ( get_option( self::OPTION_BANNER_DISMISSED, false ) ) {
				return false;
			}

			$eligible_at = get_option( self::OPTION_BANNER_ELIGIBLE_AT );
			if ( ! $eligible_at ) {
				return false;
			}

			// Show after 1 day for production.
			$delay = 86400;
			if ( time() < ( (int) $eligible_at + $delay ) ) {
				return false;
			}

			return true;
		}

		/**
		 * Static version of should_show_modal() — for use in Assets.php.
		 *
		 * @return bool
		 */
		public static function should_show_modal_static() {
			if ( self::is_flexorder_installed_static() ) {
				return false;
			}

			if ( get_option( self::OPTION_DISMISSED, false ) ) {
				return false;
			}

			return true;
		}

		/**
		 * Determines whether the modal should be shown automatically on page load.
		 * Triggered if the user has performed their first archive.
		 *
		 * @return bool
		 */
		public static function should_show_modal_auto_static() {
			if ( self::is_flexorder_installed_static() ) {
				return false;
			}

			if ( get_option( self::OPTION_DISMISSED, false ) ) {
				return false;
			}

			return (bool) get_option( self::OPTION_FIRST_ARCHIVE_PERFORMED, false );
		}

		/**
		 * Marks that the first archive operation has been performed.
		 * Hooked to archm_order_archived and archm_orders_bulk_archived.
		 *
		 * @return void
		 */
		public static function mark_first_archive_performed() {
			if ( ! get_option( self::OPTION_FIRST_ARCHIVE_PERFORMED ) ) {
				update_option( self::OPTION_FIRST_ARCHIVE_PERFORMED, true, false );
			}
		}

		/**
		 * Determines whether the modal should be shown (instance version).
		 *
		 * @return bool
		 */
		public function should_show_modal() {
			return self::should_show_modal_static();
		}

		/**
		 * Checks whether FlexOrder is installed and active (static version).
		 *
		 * @return bool
		 */
		private static function is_flexorder_active_static() {
			if ( ! function_exists( 'is_plugin_active' ) ) {
				require_once ABSPATH . 'wp-admin/includes/plugin.php';
			}

			return is_plugin_active( self::FLEXORDER_PLUGIN );
		}

		/**
		 * Checks whether FlexOrder is installed (static version).
		 *
		 * @return bool
		 */
		private static function is_flexorder_installed_static() {
			if ( ! function_exists( 'get_plugins' ) ) {
				require_once ABSPATH . 'wp-admin/includes/plugin.php';
			}

			$all_plugins = get_plugins();

			return isset( $all_plugins[ self::FLEXORDER_PLUGIN ] );
		}

		/**
		 * Checks whether FlexOrder is installed and active (instance version).
		 *
		 * @return bool
		 */
		private function is_flexorder_active() {
			return self::is_flexorder_active_static();
		}

		/**
		 * Returns the count of active orders using real-time raw SQL.
		 * Matches the dashboard's "Live Database" count exactly.
		 *
		 * Uses the same HPOS-aware logic as WcStorageHandler::get_total_count_query()
		 * to guarantee consistency with the dashboard's count.
		 *
		 * @return int
		 */
		private static function get_active_order_count_static() {
			global $wpdb;

			$is_hpos = class_exists( '\Automattic\WooCommerce\Utilities\OrderUtil' )
				&& \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled();

			if ( $is_hpos ) {
				$query = "
					SELECT COUNT(*) AS post_count
					FROM %i
					WHERE type = 'shop_order'
					AND status != 'trash'
				";
				// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Static query with no user input.
				$query = $wpdb->prepare( $query, $wpdb->prefix . 'wc_orders' );
			} else {
				$query = "
					SELECT COUNT(*) AS post_count
					FROM %i p
					WHERE p.post_type = 'shop_order'
					AND p.post_status != 'trash'
				";
				// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Static query with no user input.
				$query = $wpdb->prepare( $query, $wpdb->prefix . 'posts' );
			}

			// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Query is fully prepared above.
			return (int) $wpdb->get_var( $query );
		}

		/**
		 * Returns the active order count (instance version — delegates to static).
		 *
		 * @return int
		 */
		private function get_active_order_count() {
			return self::get_active_order_count_static();
		}
	}
}
