<?php
/**
 * This file belongs to the YIT Framework.
 *
 * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.gnu.org/licenses/gpl-3.0.txt
 *
 * @package YITH\PreOrder\Includes
 * @author YITH <plugins@yithemes.com>
 */

if ( ! defined( 'YITH_WCPO_VERSION' ) ) {
	exit( 'Direct access forbidden.' );
}

if ( ! class_exists( 'YITH_Pre_Order_Shortcodes' ) ) {
	/**
	 * Class YITH_Pre_Order_Shortcodes
	 */
	class YITH_Pre_Order_Shortcodes {

		/**
		 * Main Instance
		 *
		 * @var YITH_Pre_Order_Shortcodes
		 */
		protected static $instance;

		/**
		 * Returns single instance of the class
		 *
		 * @return YITH_Pre_Order_Shortcodes
		 */
		public static function get_instance() {
			if ( is_null( self::$instance ) ) {
				self::$instance = new self();
			}

			return self::$instance;
		}

		/**
		 * Construct
		 */
		public function __construct() {
			// [yith_wcpo_availability_date] is kept for backward compatibility. The new shortcode is [ywpo_pre_order_info].
			add_shortcode( 'yith_wcpo_availability_date', array( $this, 'availability_date_shortcode' ) );
			add_shortcode( 'ywpo_pre_order_info', array( $this, 'availability_date_shortcode' ) );
			add_shortcode( 'yith_pre_order_products', array( $this, 'pre_order_products_loop' ) );
			add_shortcode( 'yith_wcpo_my_pre_orders', array( $this, 'my_pre_orders_shortcode' ) );

			add_action( 'yith_wcpo_pagination_nav', array( $this, 'pagination_nav' ) );
		}

		/**
		 * Shortcode for displaying the pre-order info (start date or availability date).
		 * The shortcode use could be [yith_wcpo_availability_date] or [ywpo_pre_order_info].
		 *
		 * @param array $atts Shortcode attributes.
		 *
		 * @return string
		 */
		public function availability_date_shortcode( $atts ) {
			global $product;
			$fields = shortcode_atts(
				array(
					'product_id' => 0,
				),
				$atts
			);

			$product_id = false;
			if ( ! empty( $fields['product_id'] ) ) {
				$product_id = $fields['product_id'];
				$product = wc_get_product( $product_id );
			} else {
				if ( $product instanceof WC_Product ) {
					$product_id = $product->get_id();
				}
			}

			if ( $product_id && YITH_Pre_Order_Utils::is_pre_order_active( $product ) ) {
				wp_enqueue_script( 'yith-wcpo-frontend-single-product' );
				ob_start();
				$pre_order_info = apply_filters( 'ywpo_pre_order_info_shortcode', YITH_Pre_Order_Frontend_Premium::print_pre_order_info( $product, 'pre_order_single' ), $product_id );
				echo wp_kses_post( $pre_order_info );
				return ob_get_clean();
			}

			return '';
		}

		/**
		 * Shortcode for displaying Pre-Order products
		 *
		 * @param array $atts Shortcode attributes.
		 *
		 * @return string
		 */
		public function pre_order_products_loop( $atts ) {
			$atts = shortcode_atts(
				array(
					'columns'        => '4',
					'orderby'        => 'title',
					'order'          => 'asc',
					'posts_per_page' => 8,
					'show_variable'  => false,
				),
				$atts,
				'products'
			);

			$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;

			$query_args = array(
				'post_type'           => array( 'product', 'product_variation' ),
				'post_status'         => 'publish',
				'ignore_sticky_posts' => 1,
				'columns'             => $atts['columns'],
				'orderby'             => $atts['orderby'],
				'order'               => $atts['order'],
				'posts_per_page'      => $atts['posts_per_page'],
				'paged'               => $paged,
				'meta_query'          => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
					array(
						'key'     => '_ywpo_preorder',
						'value'   => 'yes',
						'compare' => '=',
					),
				),
			);

			wp_enqueue_script( 'yith-wcpo-frontend-single-product' );

			return self::product_loop( $query_args, $atts, 'yith_pre_order_products' );
		}

		/**
		 * Loop over found products.
		 *
		 * @param array  $query_args Query args.
		 * @param array  $atts       Shortcode attributes.
		 * @param string $loop_name  Loop slug.
		 *
		 * @return string
		 */
		private static function product_loop( $query_args, $atts, $loop_name ) {
			global $woocommerce_loop;

			if ( isset( $atts['show_variable'] ) && $atts['show_variable'] ) {
				$query_args['post_type'] = 'product';

				$variations_query_args                   = $query_args;
				$variations_query_args['post_type']      = 'product_variation';
				$variations_query_args['posts_per_page'] = -1;

				$simple_products_posts = get_posts( $query_args );
				$simple_products_ids   = array();
				foreach ( $simple_products_posts as $_post ) {
					$simple_products_ids[] = $_post->ID;
				}

				$variations_posts = get_posts( $variations_query_args );
				$variation_ids    = array();
				foreach ( $variations_posts as $variation ) {
					$variation_ids[ $variation->post_parent ] = '1';
				}
				$variation_ids = array_keys( $variation_ids );

				$all_pre_order_ids = array_merge( $simple_products_ids, $variation_ids );
				unset( $query_args['meta_query'] );

				$query_args['post__in'] = $all_pre_order_ids;
			}

			$products                    = new WP_Query( apply_filters( 'woocommerce_shortcode_products_query', $query_args, $atts, $loop_name ) );
			$columns                     = absint( $atts['columns'] );
			$woocommerce_loop['columns'] = $columns;
			$woocommerce_loop['name']    = $loop_name;

			ob_start();
			if ( is_singular( 'product' ) ) {
				while ( have_posts() ) {
					the_post();
					wc_get_template_part( 'content', 'single-product' );
				}
			} else {
				if ( $products->have_posts() ) {
					do_action( "woocommerce_shortcode_before_{$loop_name}_loop" );
					woocommerce_product_loop_start();

					while ( $products->have_posts() ) {
						$products->the_post();
						wc_get_template_part( 'content', 'product' );
					} // end of the loop.

					woocommerce_product_loop_end();

					do_action( "woocommerce_shortcode_after_{$loop_name}_loop" );
					do_action( 'yith_wcpo_pagination_nav', $products->max_num_pages );

				} elseif (
					! woocommerce_product_subcategories(
						array(
							'before' => woocommerce_product_loop_start( false ),
							'after'  => woocommerce_product_loop_end( false ),
						)
					)
				) {
					do_action( 'woocommerce_no_products_found' );
				}
			}

			woocommerce_reset_loop();
			wp_reset_postdata();

			return '<div class="woocommerce columns-' . $columns . '">' . ob_get_clean() . '</div>';
		}

		/**
		 * Shortcode for displaying the pre-ordered products.
		 */
		public function my_pre_orders_shortcode() {
			$orders = ywpo_get_orders_by_customer( get_current_user_id() );

			do_action( 'ywpo_my_account_my_pre_orders_before_content', $orders );

			wc_get_template(
				'myaccount/ywpo-my-pre-orders.php',
				array( 'orders' => $orders ),
				'',
				YITH_WCPO_TEMPLATE_PATH
			);

			do_action( 'ywpo_my_account_my_pre_orders_after_content', $orders );
		}

		/**
		 * Prints template for displaying navigation panel for pagination
		 *
		 * @param int $max_num_pages Number for maximum number of pages.
		 */
		public function pagination_nav( $max_num_pages ) {
			ob_start();
			wc_get_template(
				'frontend/yith-pre-order-pagination-nav.php',
				array( 'max_num_pages' => $max_num_pages ),
				'',
				YITH_WCPO_TEMPLATE_PATH
			);
			echo wp_kses_post( ob_get_clean() );
		}
	}
}

/**
 * Unique access to instance of YITH_Pre_Order_Shortcodes class
 *
 * @return YITH_Pre_Order_Shortcodes
 */
function YITH_Pre_Order_Shortcodes() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionNameInvalid
	return YITH_Pre_Order_Shortcodes::get_instance();
}
