<?php
/**
 * Admin integration.
 *
 * @package WooCommerce Subscriptions Gifting/Admin
 */

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

/**
 * Class for admin-side integration.
 */
class WCSG_Admin {

	/**
	 * Prefix used in all Gifting settings names.
	 *
	 * @var string
	 */
	public static $option_prefix = 'woocommerce_subscriptions_gifting';

	/**
	 * Setup hooks & filters, when the class is initialised.
	 */
	public static function init() {

		add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_scripts' ) );

		add_filter( 'woocommerce_subscription_list_table_column_content', __CLASS__ . '::display_recipient_name_in_subscription_title', 1, 3 );

		add_filter( 'woocommerce_order_items_meta_get_formatted', __CLASS__ . '::remove_recipient_order_item_meta', 1, 1 );

		add_filter( 'woocommerce_subscription_settings', __CLASS__ . '::add_settings' );

		if ( wcsg_is_wc_subscriptions_pre( '2.3.5' ) ) {
			add_filter( 'request', __CLASS__ . '::request_query', 11, 1 );
		} else {
			add_filter( 'wcs_admin_request_query_subscriptions_for_customer', array( __CLASS__, 'request_query_customer_filter' ), 10, 2 );
		}

		add_action( 'woocommerce_admin_order_data_after_order_details', __CLASS__ . '::display_edit_subscription_recipient_field', 10, 1 );

		// Save recipient user after WC have saved all subscription order items (40).
		add_action( 'woocommerce_process_shop_order_meta', __CLASS__ . '::save_subscription_recipient_meta', 50, 2 );

		add_action( 'admin_notices', __CLASS__ . '::admin_installed_notice' );

		// Filter for gifted subscriptions.
		add_action( 'restrict_manage_posts', array( __CLASS__, 'add_gifted_subscriptions_filter' ), 50 );
		add_action( 'woocommerce_order_list_table_restrict_manage_orders', array( __CLASS__, 'add_gifted_subscriptions_filter' ), 50 );

		add_action( 'pre_get_posts', array( __CLASS__, 'maybe_filter_by_gifted_subscriptions' ) );
		add_action( 'woocommerce_shop_subscription_list_table_prepare_items_query_args', array( __CLASS__, 'filter_subscription_list_table_by_gifted_subscriptions' ) );

		// Add "Resend new recipient account email".
		add_filter( 'woocommerce_order_actions', array( __CLASS__, 'add_resend_new_recipient_account_email_action' ), 10, 1 );
		add_action( 'woocommerce_order_action_wcsg_resend_new_recipient_account_email', array( __CLASS__, 'resend_new_recipient_account_email' ), 10, 1 );

		add_filter( 'woocommerce_hidden_order_itemmeta', array( __CLASS__, 'hide_wcsg_recipient_meta' ) );
	}

	/**
	 * Hides the wcsg_recipient meta from the order item meta in the edit order page.
	 *
	 * @param array $hidden_order_itemmeta The hidden order item meta.
	 * @return array The hidden order item meta.
	 */
	public static function hide_wcsg_recipient_meta( $hidden_order_itemmeta ) {
		$hidden_order_itemmeta[] = '_wcsg_cart_key';
		return $hidden_order_itemmeta;
	}

	/**
	 * Register/queue admin scripts.
	 */
	public static function enqueue_scripts() {
		global $post;

		$screen = get_current_screen();

		if ( 'shop_subscription' === $screen->id && WCS_Gifting::is_gifted_subscription( $post->ID ) ) {

			wp_register_script( 'wcs_gifting_admin', plugins_url( '/assets/js/gifting/wcsg-admin.js', WC_Subscriptions::$plugin_file ), array( 'jquery', 'wc-admin-order-meta-boxes' ), WC_Subscriptions::$version, true );

			wp_localize_script(
				'wcs_gifting_admin',
				'wcs_gifting',
				array(
					'revoke_download_permission_nonce' => wp_create_nonce( 'revoke_download_permission' ),
					'ajax_url'                         => admin_url( 'admin-ajax.php' ),
				)
			);

			wp_enqueue_script( 'wcs_gifting_admin' );
		}

		if ( true == get_transient( 'wcsg_show_activation_notice' ) ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
			wp_enqueue_style( 'woocommerce-activation', plugins_url( '/assets/css/activation.css', WC_PLUGIN_FILE ), array(), WC_VERSION );
		}
	}

	/**
	 * Formats the subscription title in the admin subscriptions table to include the recipient's name.
	 *
	 * @param string          $column_content The column content HTML elements.
	 * @param WC_Subscription $subscription   Subscription object.
	 * @param string          $column         The column name being rendered.
	 */
	public static function display_recipient_name_in_subscription_title( $column_content, $subscription, $column ) {

		if ( 'order_title' === $column && WCS_Gifting::is_gifted_subscription( $subscription ) ) {

			$recipient_id = WCS_Gifting::get_recipient_user( $subscription );

			if ( ! $recipient_id ) {
				return $column_content;
			}

			$recipient_user = get_userdata( $recipient_id );
			$recipient_name = '<a href="' . esc_url( get_edit_user_link( $recipient_id ) ) . '">';

			if ( ! empty( $recipient_user->first_name ) || ! empty( $recipient_user->last_name ) ) {
				$recipient_name .= ucfirst( $recipient_user->first_name ) . ( ( ! empty( $recipient_user->last_name ) ) ? ' ' . ucfirst( $recipient_user->last_name ) : '' );
			} else {
				$recipient_name .= ucfirst( $recipient_user->display_name );
			}
			$recipient_name .= '</a>';

			$purchaser_id   = $subscription->get_user_id();
			$purchaser_user = get_userdata( $purchaser_id );
			$purchaser_name = '<a href="' . esc_url( get_edit_user_link( $purchaser_id ) ) . '">';

			if ( ! empty( $purchaser_user->first_name ) || ! empty( $purchaser_user->last_name ) ) {
				$purchaser_name .= ucfirst( $purchaser_user->first_name ) . ( ( ! empty( $purchaser_user->last_name ) ) ? ' ' . ucfirst( $purchaser_user->last_name ) : '' );
			} else {
				$purchaser_name .= ucfirst( $purchaser_user->display_name );
			}
			$purchaser_name .= '</a>';

			// translators: $1: is subscription order number,$2: is recipient user's name, $3: is the purchaser user's name.
			$column_content = sprintf( _x( '%1$s for %2$s purchased by %3$s', 'Subscription title on admin table. (e.g.: #211 for John Doe Purchased by: Jane Doe)', 'woocommerce-subscriptions' ), '<a href="' . esc_url( $subscription->get_edit_order_url() ) . '">#<strong>' . esc_attr( $subscription->get_order_number() ) . '</strong></a>', $recipient_name, $purchaser_name );

			$column_content .= '</div>';
		}

		return $column_content;
	}

	/**
	 * Removes the recipient order item meta from the admin subscriptions table.
	 *
	 * @param array $formatted_meta formatted order item meta key, label and value.
	 */
	public static function remove_recipient_order_item_meta( $formatted_meta ) {

		if ( is_admin() ) {
			$screen = get_current_screen();

			if ( isset( $screen->id ) && 'edit-shop_subscription' === $screen->id ) {
				foreach ( $formatted_meta as $meta_id => $meta ) {
					if ( 'wcsg_recipient' === $meta['key'] ) {
						unset( $formatted_meta[ $meta_id ] );
					}
				}
			}
		}

		return $formatted_meta;
	}

	/**
	 * Add Gifting specific settings to standard Subscriptions settings
	 *
	 * @param array $settings  Current set of settings.
	 * @return array $settings New set of settings.
	 */
	public static function add_settings( $settings ) {
		$gifting_settings = array(
			array(
				'name' => __( 'Gifting', 'woocommerce-subscriptions' ),
				'type' => 'title',
				'id'   => self::$option_prefix,
			),
			array(
				'name'      => __( 'Enable gifting', 'woocommerce-subscriptions' ),
				'desc'      => __( 'Allow shoppers to gift a subscription', 'woocommerce-subscriptions' ),
				'id'        => self::$option_prefix . '_enable_gifting',
				'default'   => 'no',
				'type'      => 'checkbox',
				'row_class' => 'enable-gifting',
			),
			array(
				'name'        => '',
				'desc'        => __( 'You can override this global setting on each product.', 'woocommerce-subscriptions' ),
				'id'          => self::$option_prefix . '_default_option',
				'default'     => 'disabled',
				'type'        => 'radio',
				'desc_at_end' => true,
				'row_class'   => 'gifting-radios',
				'options'     => array(
					'enabled'  => __( 'Enabled for all products', 'woocommerce-subscriptions' ),
					'disabled' => __( 'Disabled for all products', 'woocommerce-subscriptions' ),
				),
			),
			array(
				'name'      => __( 'Gifting Checkbox Text', 'woocommerce-subscriptions' ),
				'desc'      => __( 'This is what shoppers will see in the product page and cart.', 'woocommerce-subscriptions' ),
				'id'        => self::$option_prefix . '_gifting_checkbox_text',
				'default'   => __( 'This is a gift', 'woocommerce-subscriptions' ),
				'type'      => 'text',
				'row_class' => 'gifting-checkbox-text',
			),
			array(
				'type' => 'sectionend',
				'id'   => self::$option_prefix,
			),
		);

		if ( ! WC_Subscriptions_Admin::insert_setting_after( $settings, WC_Subscriptions_Admin::$option_prefix . '_renewal_options', $gifting_settings, 'multiple_settings', 'sectionend' ) ) {
			return array_merge( $settings, $gifting_settings );
		}

		return $settings;
	}

	/**
	 * Adds meta query to also include subscriptions the user is the recipient of when filtering subscriptions by customer.
	 * Compatibility method for Subscriptions < 2.3.5.
	 *
	 * @param  array $vars Request vars.
	 * @return array
	 */
	public static function request_query( $vars ) {
		global $typenow;

		if ( 'shop_subscription' === $typenow ) {

			// Add _recipient_user meta check when filtering by customer.
			$user_id = isset( $_GET['_customer_user'] ) ? intval( $_GET['_customer_user'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			if ( $user_id ) {
				$vars['meta_query'][] = array(
					'key'     => '_recipient_user',
					'value'   => $user_id,
					'compare' => '=',
				);

				$vars['meta_query']['relation'] = 'OR';
			}
		}

		return $vars;
	}

	/**
	 * Adds subscriptions the user is the recipient of when filtering subscriptions by customer on the backend.
	 *
	 * @param array $subscription_ids Current set of subscription IDs.
	 * @param int   $customer_user_id User ID.
	 * @return array New set of subscription IDs.
	 * @since 7.8.0 - Originally implemented in WooCommerce Subscriptions Gifting  2.0.2.
	 */
	public static function request_query_customer_filter( $subscription_ids, $customer_user_id ) {
		$recipient_subscriptions = WCSG_Recipient_Management::get_recipient_subscriptions( $customer_user_id );
		return array_merge( $subscription_ids, $recipient_subscriptions );
	}

	/**
	 * Output a recipient user select field in the edit subscription data metabox.
	 *
	 * @param WP_Post $subscription Subscription's post object.
	 * @since 7.8.0 - Originally implemented in WooCommerce Subscriptions Gifting 1.0.1.
	 */
	public static function display_edit_subscription_recipient_field( $subscription ) {

		if ( ! wcs_is_subscription( $subscription ) ) {
			return;
		} ?>

		<p class="form-field form-field-wide wc-customer-user">
			<label for="recipient_user"><?php esc_html_e( 'Recipient:', 'woocommerce-subscriptions' ); ?></label>
			<?php
			$user_string = '';
			$user_id     = '';
			if ( WCS_Gifting::is_gifted_subscription( $subscription ) ) {
				$user_id = WCS_Gifting::get_recipient_user( $subscription );

				if ( $user_id ) {
					$user        = get_user_by( 'id', $user_id );
					$user_string = esc_html( $user->display_name ) . ' (#' . absint( $user->ID ) . ' &ndash; ' . esc_html( $user->user_email );
				}
			}

			if ( is_callable( array( 'WCS_Select2', 'render' ) ) ) {
				WCS_Select2::render(
					array(
						'class'       => 'wc-customer-search',
						'name'        => 'recipient_user',
						'id'          => 'recipient_user',
						'placeholder' => esc_attr__( 'Search for a recipient&hellip;', 'woocommerce-subscriptions' ),
						'selected'    => $user_string,
						'value'       => $user_id,
						'allow_clear' => 'true',
					)
				);
			} else {
				?>
				<input type="hidden" class="wc-customer-search" id="recipient_user" name="recipient_user" data-placeholder="<?php esc_attr_e( 'Search for a recipient&hellip;', 'woocommerce-subscriptions' ); ?>" data-selected="<?php echo esc_attr( $user_string ); ?>" value="<?php echo esc_attr( $user_id ); ?>" data-allow_clear="true"/>
				<?php
			}
			?>
		</p>
		<?php
	}

	/**
	 * Save subscription recipient user meta by updating or deleting _recipient_user post meta.
	 * Also updates the recipient id stored in subscription line item meta.
	 *
	 * @param int     $post_id  Post ID.
	 * @param WP_Post $post     Post object.
	 * @since 7.8.0 - Originally implemented in WooCommerce Subscriptions Gifting 1.0.1.
	 */
	public static function save_subscription_recipient_meta( $post_id, $post ) {

		if ( 'shop_subscription' !== WC_Data_Store::load( 'subscription' )->get_order_type( $post_id ) || empty( $_POST['woocommerce_meta_nonce'] ) || ! wp_verify_nonce( $_POST['woocommerce_meta_nonce'], 'woocommerce_save_data' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
			return;
		}

		$recipient_user         = empty( $_POST['recipient_user'] ) ? '' : absint( $_POST['recipient_user'] );
		$subscription           = wcs_get_subscription( $post_id );
		$customer_user          = $subscription->get_user_id();
		$is_gifted_subscription = WCS_Gifting::is_gifted_subscription( $subscription );

		if ( $recipient_user == $customer_user ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
			// Remove the recipient.
			$recipient_user = '';
			wcs_add_admin_notice( __( 'Error saving subscription recipient: customer and recipient cannot be the same. The recipient user has been removed.', 'woocommerce-subscriptions' ), 'error' );
		}

		if ( ( $is_gifted_subscription && WCS_Gifting::get_recipient_user( $subscription ) == $recipient_user ) || ( ! $is_gifted_subscription && empty( $recipient_user ) ) ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
			// Recipient user remains unchanged - do nothing.
			return;
		} elseif ( empty( $recipient_user ) ) {
			WCS_Gifting::delete_recipient_user( $subscription );

			// Delete recipient meta from subscription order items.
			foreach ( $subscription->get_items() as $order_item_id => $order_item ) {
				wc_delete_order_item_meta( $order_item_id, 'wcsg_recipient' );
			}
		} else {
			WCS_Gifting::set_recipient_user( $subscription, $recipient_user );

			// Update all subscription order items.
			foreach ( $subscription->get_items() as $order_item_id => $order_item ) {
				wc_update_order_item_meta( $order_item_id, 'wcsg_recipient', 'wcsg_recipient_id_' . $recipient_user );
			}
		}
	}

	/**
	 * Outputs a welcome message. Called when the Subscriptions extension is activated.
	 *
	 * @since 7.8.0 - Originally implemented in WooCommerce Subscriptions Gifting 2.0.0.
	 */
	public static function admin_installed_notice() {

		if ( true == get_transient( 'wcsg_show_activation_notice' ) ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
			wc_get_template( 'activation-notice.php', array( 'settings_tab_url' => self::settings_tab_url() ), '', plugin_dir_path( WC_Subscriptions::$plugin_file ) . 'templates/gifting/' );
			delete_transient( 'wcsg_show_activation_notice' );
		}
	}

	/**
	 * A WooCommerce version aware function for getting the Subscriptions/Gifting admin settings tab URL.
	 *
	 * @since 7.8.0 - Originally implemented in WooCommerce Subscriptions Gifting 2.0.0.
	 * @return string
	 */
	public static function settings_tab_url() {
		return apply_filters( 'woocommerce_subscriptions_settings_tab_url', admin_url( 'admin.php?page=wc-settings&tab=subscriptions' ) );
	}

	/**
	 * Adds a dropdown to the Subscriptions admin screen to allow filtering by gifted subscriptions.
	 *
	 * @param string $post_type Current post type.
	 * @since 7.8.0 - Originally implemented in WooCommerce Subscriptions Gifting 2.0.3.
	 */
	public static function add_gifted_subscriptions_filter( $post_type = '' ) {
		$post_type = ! empty( $post_type ) ? $post_type : $GLOBALS['typenow'];

		if ( 'shop_subscription' !== $post_type ) {
			return;
		}

		$gifted_subscriptions = WCS_Gifting::get_gifted_subscriptions(
			array(
				'limit'  => 1,
				'return' => 'ids',
			)
		);
		if ( empty( $gifted_subscriptions ) ) {
			return;
		}

		$options        = array(
			''      => __( 'All Subscriptions', 'woocommerce-subscriptions' ),
			'true'  => __( 'Gifted Subscriptions', 'woocommerce-subscriptions' ),
			'false' => __( 'Non-gifted subscriptions', 'woocommerce-subscriptions' ),
		);
		$wcsg_is_gifted = isset( $_GET['wcsg_is_gifted'] ) ? $_GET['wcsg_is_gifted'] : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash

		echo '<select class="wcsg_is_gifted_selector last" name="wcsg_is_gifted" id="wcsg_is_gifted">';
		foreach ( $options as $value => $text ) {
			echo '<option value="' . esc_attr( $value ) . '" ' . selected( $value, $wcsg_is_gifted, false ) . '>' . esc_html( $text ) . '</option>';
		}
		echo '</select>';
	}

	/**
	 * Filters the main admin query to include only gifted or non-gifted subscriptions.
	 *
	 * @param WP_Query $query The WP_Query instance (passed by reference).
	 * @since 7.8.0 - Originally implemented in WooCommerce Subscriptions Gifting 2.0.3.
	 */
	public static function maybe_filter_by_gifted_subscriptions( $query ) {
		global $typenow;

		if ( ! is_admin() || ! $query->is_main_query() || 'shop_subscription' !== $typenow || ! isset( $_GET['wcsg_is_gifted'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			return;
		}

		$wcsg_is_gifted = trim( $_GET['wcsg_is_gifted'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash

		$compare = '';
		if ( 'true' === $wcsg_is_gifted ) {
			$compare = 'EXISTS';
		} elseif ( 'false' === $wcsg_is_gifted ) {
			$compare = 'NOT EXISTS';
		}

		if ( ! $compare ) {
			return;
		}

		$meta_query = $query->get( 'meta_query' );
		if ( ! $meta_query ) {
			$meta_query = array();
		}

		$meta_query[] = array(
			'key'     => '_recipient_user',
			'compare' => $compare,
		);

		$query->set( 'meta_query', $meta_query );
	}

	/**
	 * Filter the Subscriptions Admin Table to filter only gifted or non-gifted subscriptions.
	 *
	 * @param array $request_query The query args sent to wc_get_orders().
	 */
	public static function filter_subscription_list_table_by_gifted_subscriptions( $request_query ) {
		/**
		 * Note this request isn't nonced as we're only filtering a list table and not modifying data.
		 */
		if ( ! isset( $_GET['wcsg_is_gifted'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
			return $request_query;
		}

		$wcsg_is_gifted = trim( $_GET['wcsg_is_gifted'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash

		if ( ! in_array( $wcsg_is_gifted, array( 'true', 'false' ), true ) ) {
			return $request_query;
		}

		$request_query['meta_query'][] = array(
			'key'     => '_recipient_user',
			'compare' => 'true' === $wcsg_is_gifted ? 'EXISTS' : 'NOT EXISTS',
		);

		return $request_query;
	}

	/**
	 * Adds actions to the admin edit subscriptions page, if the subscription is a gifted one.
	 *
	 * @param array $actions Current admin actions.
	 * @return array $actions The subscription actions with the "Renew Now" action added if it's permitted.
	 *
	 * @since 7.8.0 - Originally implemented in WooCommerce Subscriptions Gifting 2.1.0.
	 */
	public static function add_resend_new_recipient_account_email_action( $actions ) {
		global $theorder;

		if ( WCS_Gifting::is_gifted_subscription( $theorder ) ) {
			$actions['wcsg_resend_new_recipient_account_email'] = __( 'Resend "new recipient account" email', 'woocommerce-subscriptions' );
		}

		return $actions;
	}

	/**
	 * Resends the "new recipient" e-mail.
	 *
	 * @param WC_Order $subscription Subscription object.
	 *
	 * @since 7.8.0 - Originally implemented in WooCommerce Subscriptions Gifting 2.1.0.
	 */
	public static function resend_new_recipient_account_email( $subscription ) {
		if ( WCS_Gifting::is_gifted_subscription( $subscription->get_id() ) ) {
			WCSG_Email::resend_new_recipient_user_email( $subscription );
		}
	}

	/**
	 * Get enable gifting setting.
	 *
	 * @return bool
	 */
	public static function is_gifting_enabled() {
		$global_enable_gifting = get_option( self::$option_prefix . '_enable_gifting', 'no' );

		return apply_filters( 'wcsg_enable_gifting', 'yes' === $global_enable_gifting );
	}

	/**
	 * Get if gifting is enabled by default for all products.
	 *
	 * @return bool
	 */
	public static function is_gifting_enabled_for_all_products() {
		$global_default_option = get_option( self::$option_prefix . '_default_option', 'disabled' );

		return apply_filters( 'wcsg_is_enabled_for_all_products', 'enabled' === $global_default_option );
	}

	/**
	 * Get the text for the gifting option.
	 *
	 * @return string
	 */
	public static function get_gifting_option_text() {
		return self::is_gifting_enabled_for_all_products()
			? __( 'Follow global setting (enabled)', 'woocommerce-subscriptions' )
			: __( 'Follow global setting (disabled)', 'woocommerce-subscriptions' );
	}

	/**
	 * Get the text for the gifting option.
	 */
	public static function get_gifting_global_override_text() {
		?>
		<p class="_subscription_gifting_field_description form-field">
			<span class="description">
				<?php
				/* translators: %1$s opening anchor tag with url, %2$s closing anchor tag */
				$gifting_description = __( 'Overriding your %1$sstore\'s settings%2$s', 'woocommerce-subscriptions' );

				echo wp_kses_post(
					sprintf(
						$gifting_description,
						'<a href="' . admin_url( 'admin.php?page=wc-settings&tab=subscriptions#woocommerce_subscriptions_gifting_enable_gifting' ) . '">',
						'</a>'
					)
				);
				?>
			</span>
		</p>
		<?php
	}
}
