<?php
/**
 * Admin class
 *
 * @author  YITH <plugins@yithemes.com>
 * @package YITH\ProductBundles
 */

defined( 'YITH_WCPB' ) || exit;

if ( ! class_exists( 'YITH_WCPB_Admin' ) ) {
	/**
	 * Admin class.
	 * The class manage all the admin behaviors.
	 */
	class YITH_WCPB_Admin {

		/**
		 * Single instance of the class
		 *
		 * @var YITH_WCPB_Admin
		 */
		protected static $instance;

		/**
		 * Plugin version
		 *
		 * @var string
		 */
		public $version = YITH_WCPB_VERSION;

		/**
		 * Panel Object
		 *
		 * @var YIT_Plugin_Panel_WooCommerce
		 */
		protected $panel;

		/**
		 * Premium version landing link
		 *
		 * @var string
		 */
		protected $premium_landing = 'https://yithemes.com/themes/plugins/yith-woocommerce-product-bundles';

		/**
		 * The panel page
		 *
		 * @var string
		 */
		protected $panel_page = 'yith_wcpb_panel';

		/**
		 * Returns single instance of the class
		 *
		 * @return YITH_WCPB_Admin|YITH_WCPB_Admin_Premium
		 */
		public static function get_instance() {
			/**
			 * The class.
			 *
			 * @var YITH_WCPB_Admin|YITH_WCPB_Admin_Premium $self
			 */
			$self = __CLASS__ . ( class_exists( __CLASS__ . '_Premium' ) ? '_Premium' : '' );

			return ! is_null( $self::$instance ) ? $self::$instance : $self::$instance = new $self();
		}

		/**
		 * Constructor
		 */
		protected function __construct() {

			add_action( 'admin_menu', array( $this, 'register_panel' ), 5 );

			add_filter( 'plugin_action_links_' . plugin_basename( YITH_WCPB_DIR . '/' . basename( YITH_WCPB_FILE ) ), array( $this, 'action_links' ) );
			add_filter( 'yith_show_plugin_row_meta', array( $this, 'plugin_row_meta' ), 10, 3 );

			add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ), 20 );

			add_filter( 'woocommerce_product_data_tabs', array( $this, 'woocommerce_product_data_tabs' ) );
			add_action( 'woocommerce_product_data_panels', array( $this, 'woocommerce_product_data_panels' ) );

			add_action( 'wp_ajax_yith_wcpb_select_product_box', array( $this, 'select_product_box' ) );
			add_action( 'wp_ajax_yith_wcpb_select_product_box_filtered', array( $this, 'select_product_box_filtered' ) );
			add_action( 'wp_ajax_yith_wcpb_add_product_in_bundle', array( $this, 'add_product_in_bundle' ) );

			add_action( 'woocommerce_admin_process_product_object', array( $this, 'woocommerce_process_product_meta' ) );

			add_action( 'yith_wcpb_admin_bundled_item_options', array( $this, 'print_bundled_item_options' ), 10, 2 );

			add_filter( 'woocommerce_admin_html_order_item_class', array( $this, 'woocommerce_admin_html_order_item_class' ), 10, 2 );
			add_filter( 'woocommerce_admin_order_item_class', array( $this, 'woocommerce_admin_html_order_item_class' ), 10, 2 );
			add_filter( 'woocommerce_admin_order_item_count', array( $this, 'woocommerce_admin_order_item_count' ), 10, 2 );
			add_filter( 'woocommerce_hidden_order_itemmeta', array( $this, 'woocommerce_hidden_order_itemmeta' ) );
			add_filter( 'woocommerce_order_item_display_meta_key', array( $this, 'woocommerce_order_item_display_meta_key' ) );

			add_action( 'wp_ajax_woocommerce_add_order_item', array( $this, 'prevent_adding_bundle_products_in_orders' ), 5 );

			add_action( 'yith_wcpb_premium_tab', array( $this, 'show_premium_tab' ) );
			add_action( 'yith_wcpb_how_to_tab', array( $this, 'show_how_to_tab' ) );
		}

		/**
		 * Hide bundled_by meta in admin order
		 *
		 * @param array $hidden Hidden columns.
		 *
		 * @return array
		 */
		public function woocommerce_hidden_order_itemmeta( $hidden ) {
			return array_merge( $hidden, array( '_bundled_by', '_cartstamp' ) );
		}

		/**
		 * Filter display meta key
		 *
		 * @param string $display_key The key to be shown.
		 *
		 * @return string
		 */
		public function woocommerce_order_item_display_meta_key( $display_key ) {
			if ( '_yith_wcpb_title' === $display_key ) {
				$display_key = __( 'Custom name', 'yith-woocommerce-product-bundles' );
			}

			return $display_key;
		}

		/**
		 * Add CSS class in admin order bundled items
		 *
		 * @param string $class The class.
		 * @param array  $item  The item.
		 *
		 * @return string
		 */
		public function woocommerce_admin_html_order_item_class( $class, $item ) {
			if ( isset( $item['bundled_by'] ) ) {
				return $class . ' yith-wcpb-admin-bundled-item';
			}

			return $class;
		}

		/**
		 * Filter item count in admin orders page
		 *
		 * @param int      $count The count.
		 * @param WC_Order $order The order.
		 *
		 * @return int|string
		 */
		public function woocommerce_admin_order_item_count( $count, $order ) {
			$counter = 0;
			foreach ( $order->get_items() as $item ) {
				if ( isset( $item['bundled_by'] ) ) {
					$counter += $item['qty'];
				}
			}
			if ( $counter > 0 ) {
				$non_bundled_count = $count - $counter;

				// translators: 1: number of items; 2: number of elements included in the bundle.
				return sprintf( _n( '%1$s item [%2$s bundled elements]', '%1$s items [%2$s bundled elements]', $non_bundled_count, 'yith-woocommerce-product-bundles' ), $non_bundled_count, $counter );
			}

			return $count;
		}

		/**
		 * Add Product Bundle type in product type selector [in product wc-metabox]
		 *
		 * @param array $types Product types.
		 *
		 * @return array
		 * @deprecated 1.4.11 | use YITH_WCPB:product_type_selector instead.
		 */
		public function product_type_selector( $types ) {
			_deprecated_function( 'YITH_WCPB_Admin::product_type_selector', '1.4.11', 'YITH_WCPB:product_type_selector' );

			return yith_wcpb()->product_type_selector( $types );
		}

		/**
		 * Print bundled item options.
		 *
		 * @param YITH_WC_Bundled_Item $bundled_item The item.
		 * @param int                  $metabox_id   The metabox ID.
		 *
		 * @since 1.4.0
		 */
		public function print_bundled_item_options( $bundled_item, $metabox_id ) {
			yith_wcpb_get_view( '/admin/bundled-item-options.php', compact( 'bundled_item', 'metabox_id' ) );
		}

		/**
		 * Render Select Product Box.
		 */
		public function select_product_box() {
			yith_wcpb_get_view( '/admin/select-product-box.php' );
			die();
		}

		/**
		 * Render Select Product Box Filtered.
		 */
		public function select_product_box_filtered() {
			yith_wcpb_get_view( '/admin/select-product-box-products.php' );
			die();
		}

		/**
		 * Ajax Called in bundle_options_metabox.js
		 * return the empty form for the item
		 */
		public function add_product_in_bundle() {
			$response = array();
			if ( check_ajax_referer( 'yith-wcpb-add-product-to-bundle', 'security', false ) && isset( $_POST['id'], $_POST['bundle_id'], $_POST['product_id'] ) ) {
				$metabox_id = intval( $_POST['id'] );
				$bundle_id  = absint( $_POST['bundle_id'] );
				$product_id = absint( $_POST['product_id'] );
				$product    = wc_get_product( $product_id );

				if ( $product instanceof WC_Product && ! $product->is_type( 'simple' ) ) {
					$response['error'] = esc_html__( 'You can add only simple products with the FREE version of YITH WooCommerce Product Bundles', 'yith-woocommerce-product-bundles' );
				} else {
					$bundle_product = wc_get_product( $bundle_id );
					$bundled_item   = new YITH_WC_Bundled_Item( $bundle_product, $metabox_id, compact( 'product_id' ) );
					ob_start();
					yith_wcpb_get_view( '/admin/bundled-item.php', compact( 'metabox_id', 'bundled_item' ) );
					$response['html'] = ob_get_clean();
				}
			} else {
				$response['error'] = esc_html__( 'Something went wrong. Try again!', 'yith-woocommerce-product-bundles' );
			}
			wp_send_json( $response );
		}

		/**
		 * Add Bundle Options Tab [in product wc-metabox].
		 *
		 * @param array $product_tabs Product tabs.
		 *
		 * @return array
		 */
		public function woocommerce_product_data_tabs( $product_tabs ) {
			$product_tabs['yith_bundle_options'] = array(
				'label'  => __( 'Bundle Options', 'yith-woocommerce-product-bundles' ),
				'target' => 'yith_bundle_product_data',
				'class'  => array( 'show_if_yith_bundle' ),
			);

			$product_tabs['inventory']['class'] = array_merge( $product_tabs['inventory']['class'], array( 'show_if_yith_bundle' ) );

			return $product_tabs;
		}

		/**
		 * Add panel for Bundle Options Tab [in product wc-metabox]
		 */
		public function woocommerce_product_data_panels() {
			/**
			 * The product.
			 *
			 * @var WC_Product $product_object
			 */
			global $product_object;

			$bundle_product = $product_object->is_type( 'yith_bundle' ) ? $product_object : false;

			yith_wcpb_get_view( '/admin/bundle-options-tab.php', compact( 'bundle_product', 'product_object' ) );
		}

		/**
		 * Set the product meta before saving the product
		 *
		 * @param WC_Product_YITH_Bundle $product The product.
		 */
		public function woocommerce_process_product_meta( $product ) {
			if ( $product->is_type( 'yith_bundle' ) ) {

				// phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
				$bundle_data         = ! empty( $_POST['_yith_wcpb_bundle_data'] ) && is_array( $_POST['_yith_wcpb_bundle_data'] ) ? wp_unslash( $_POST['_yith_wcpb_bundle_data'] ) : array();
				$indexed_bundle_data = array();
				if ( $bundle_data ) {
					$loop = 1;
					foreach ( $bundle_data as $single_bundle_data ) {

						foreach ( $single_bundle_data as $key => $value ) {
							if ( in_array( $key, array( 'bp_title', 'bp_description' ), true ) ) {
								$single_bundle_data[ $key ] = wp_kses_post( $single_bundle_data[ $key ] );
							} else {
								$single_bundle_data[ $key ] = wc_clean( $single_bundle_data[ $key ] );
							}
						}

						$indexed_bundle_data[ $loop ] = $single_bundle_data;
						$loop ++;
					}
				}

				$product->update_meta_data( '_yith_wcpb_bundle_data', $indexed_bundle_data );
				$product->update_meta_data( '_yith_bundle_product_version', yith_wcpb()->get_bundle_product_version() );
			}
		}

		/**
		 * Action Links
		 * add the action links to plugin admin page
		 *
		 * @param array $links The links.
		 *
		 * @return   array
		 * @use      plugin_action_links_{$plugin_file_name}
		 */
		public function action_links( $links ) {
			return yith_add_action_links( $links, $this->panel_page, defined( 'YITH_WCPB_PREMIUM' ), YITH_WCPB_SLUG );
		}

		/**
		 * Adds row meta.
		 *
		 * @param array    $row_meta_args Row meta arguments.
		 * @param string[] $plugin_meta   An array of the plugin's metadata,
		 *                                including the version, author,
		 *                                author URI, and plugin URI.
		 * @param string   $plugin_file   Path to the plugin file relative to the plugins directory.
		 *
		 * @return array
		 */
		public function plugin_row_meta( $row_meta_args, $plugin_meta, $plugin_file ) {
			$init = defined( 'YITH_WCPB_FREE_INIT' ) ? YITH_WCPB_FREE_INIT : YITH_WCPB_INIT;

			if ( $init === $plugin_file ) {
				$row_meta_args['slug']       = YITH_WCPB_SLUG;
				$row_meta_args['is_premium'] = defined( 'YITH_WCPB_PREMIUM' );
			}

			return $row_meta_args;
		}

		/**
		 * Retrieve Panel tabs.
		 *
		 * @return array
		 * @since 1.8.0
		 */
		protected function get_panel_tabs() {
			$tabs = array(
				'how-to' => array(
					'title'       => __( 'How to create Product Bundles', 'yith-woocommerce-product-bundles' ), // TODO Maybe change title?
					'icon'        => 'help',
					'description' => '',
				),
			);

			return apply_filters( 'yith_wcpb_settings_admin_tabs', $tabs );
		}

		/**
		 * Retrieve Panel arguments.
		 *
		 * @return array
		 * @since 1.8.0
		 */
		protected function get_panel_args() {
			return array(
				'ui_version'       => 2,
				'create_menu_page' => true,
				'parent_slug'      => '',
				'class'            => yith_set_wrapper_class(),
				'page_title'       => 'YITH WooCommerce Product Bundles',
				'menu_title'       => 'Product Bundles',
				'capability'       =>  apply_filters( 'ywcpb_settings_panel_capabilities', 'manage_options' ),
				'parent'           => '',
				'parent_page'      => 'yit_plugin_panel',
				'page'             => $this->panel_page,
				'admin-tabs'       => $this->get_panel_tabs(),
				'options-path'     => YITH_WCPB_DIR . '/plugin-options',
				'plugin_slug'      => YITH_WCPB_SLUG,
				'is_free'          => true,
				'premium_tab'      => array(
					'features' => array(
						array(
							'title'       => __( 'Add variable products to the bundle and set each item as optional or required', 'yith-woocommerce-product-bundles' ),
							'description' => __( 'In the premium version you can add product variations to the bundle and decide whether to make some products optional, allowing customers to remove them from the bundle.', 'yith-woocommerce-product-bundles' ),
						),
						array(
							'title'       => __( 'Customize every aspect of the products shown in the bundle', 'yith-woocommerce-product-bundles' ),
							'description' => __( 'Hide the product image, change the title, and insert an ad hoc description to display the bundled products in an appealing way.', 'yith-woocommerce-product-bundles' ),
						),
						array(
							'title'       => __( 'Additional pricing options', 'yith-woocommerce-product-bundles' ),
							'description' => __( 'You can set a fixed price for the bundle (without adding up the price of individual products) and apply a fixed or percentage discount. Decide whether to display the amount of money a customer can save by buying the package.', 'yith-woocommerce-product-bundles' ),
						),
						array(
							'title'       => __( 'More versatile shipping options', 'yith-woocommerce-product-bundles' ),
							'description' => __( 'With the upgraded version, you can decide if you want to dispatch the items in the package separately or all together in a single shipment, and adjust the shipping fees accordingly.', 'yith-woocommerce-product-bundles' ),
						),
						array(
							'title'       => __( 'Set limits and rules for bundle purchases', 'yith-woocommerce-product-bundles' ),
							'description' => __( 'Do your bundles need advanced configuration? You can choose the minimum and maximum number of products that can be purchased together in the bundle. Additionally, you can set a minimum number of items that should be bought to qualify for the bundle purchase. By doing so, only those who meet the conditions you set will be able to purchase it.', 'yith-woocommerce-product-bundles' ),
						),
					),
				),
			);
		}

		/**
		 * Add a panel under YITH Plugins tab
		 */
		public function register_panel() {

			if ( ! empty( $this->panel ) ) {
				return;
			}

			$args = $this->get_panel_args();

			$this->panel = new YIT_Plugin_Panel_WooCommerce( $args );
		}

		/**
		 * Don't allow adding bundle to orders through "Add products" box in orders.
		 *
		 * @since 1.2.21
		 */
		public function prevent_adding_bundle_products_in_orders() {
			if ( isset( $_POST['data'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
				$items_to_add = array_filter( wp_unslash( (array) $_POST['data'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized

				$bundle_titles = array();
				foreach ( $items_to_add as $item ) {
					if ( ! isset( $item['id'], $item['qty'] ) || empty( $item['id'] ) ) {
						continue;
					}
					$product_id = absint( $item['id'] );
					$product    = wc_get_product( $product_id );
					if ( $product && $product->is_type( 'yith_bundle' ) ) {
						$bundle_titles[] = $product->get_formatted_name();
					}
				}

				if ( $bundle_titles ) {
					// translators: %s is a comma-separated list of bundle products.
					wp_send_json_error( array( 'error' => sprintf( __( 'You are trying to add the following Bundle products to the order: %s. You cannot add Bundle products to orders through this box since this type of products needs to follow the normal WooCommerce "Add-to-cart > Cart > Checkout > Order" process.', 'yith-woocommerce-product-bundles' ), implode( ', ', $bundle_titles ) ) ) );
				}
			}
		}

		/**
		 * Enqueue scripts
		 */
		public function admin_enqueue_scripts() {
			$screen     = get_current_screen();
			$metabox_js = defined( 'YITH_WCPB_PREMIUM' ) ? 'bundle_options_metabox_premium.js' : 'bundle_options_metabox.js';

			wp_enqueue_style( 'yith-wcpb-admin-styles', YITH_WCPB_ASSETS_URL . '/css/admin.css', array(), YITH_WCPB_VERSION );
			wp_register_style( 'yith-wcpb-popup', YITH_WCPB_ASSETS_URL . '/css/yith-wcpb-popup.css', array(), YITH_WCPB_VERSION );

			wp_register_script( 'yith-wcpb-popup', yit_load_js_file( YITH_WCPB_ASSETS_URL . '/js/yith-wcpb-popup.js' ), array( 'jquery' ), YITH_WCPB_VERSION, true );
			wp_register_script( 'yith_wcpb_bundle_options_metabox', yit_load_js_file( YITH_WCPB_ASSETS_URL . '/js/' . $metabox_js ), array( 'jquery', 'jquery-ui-sortable', 'yith-wcpb-popup' ), YITH_WCPB_VERSION, true );

			if ( 'product' === $screen->id ) {
				wp_enqueue_style( 'yith-wcpb-popup' );
				wp_enqueue_style( 'yith-plugin-fw-fields' );

				wp_enqueue_script( 'yith-plugin-fw-fields' );
				wp_enqueue_script( 'yith_wcpb_bundle_options_metabox' );

				// TODO: to remove. It was kept for backward compatibility.
				wp_localize_script(
					'yith_wcpb_bundle_options_metabox',
					'ajax_object',
					array(
						'free_not_simple'     => __( 'You can add only simple products with the FREE version of YITH WooCommerce Product Bundles', 'yith-woocommerce-product-bundles' ),
						'yith_bundle_product' => __( 'You cannot add a bundle product', 'yith-woocommerce-product-bundles' ),
						'minimum_characters'  => apply_filters( 'yith_wcpb_minimum_characters_ajax_search', 3 ),
					)
				);

				wp_localize_script(
					'yith_wcpb_bundle_options_metabox',
					'yith_bundle_opts',
					array(
						'i18n'               => array(
							// translators: %s is the number of items added.
							'addedLabelSingular' => esc_html( sprintf( _n( '%s item added', '%s items added', 1, 'yith-woocommerce-product-bundles' ), 1 ) ),
							// translators: %s is the number of items added.
							'addedLabelPlural'   => esc_html( _n( '%s item added', '%s items added', 2, 'yith-woocommerce-product-bundles' ) ),
						),
						'minimum_characters' => apply_filters( 'yith_wcpb_minimum_characters_ajax_search', 3 ),
						'nonces'             => array(
							'addProductToBundle' => wp_create_nonce( 'yith-wcpb-add-product-to-bundle' ),
						),
					)
				);
			}
		}

		/**
		 * Show premium landing tab
		 */
		public function show_how_to_tab() {
			$landing = YITH_WCPB_TEMPLATE_PATH . '/how-to.php';
			file_exists( $landing ) && require $landing;
		}

		/**
		 * Get the premium landing uri
		 *
		 * @return  string
		 */
		public function get_premium_landing_uri() {
			return apply_filters( 'yith_plugin_fw_premium_landing_uri', $this->premium_landing, YITH_WCPB_SLUG );
		}
	}
}

/**
 * Unique access to instance of YITH_WCPB_Admin class
 *
 * @return YITH_WCPB_Admin|YITH_WCPB_Admin_Premium
 */
function yith_wcpb_admin() {
	return YITH_WCPB_Admin::get_instance();
}
