<?php

namespace Prodigy\Includes\Frontend\Pages;

use Prodigy\Includes\Content\Prodigy_Product_Parser;
use Prodigy\Includes\Content\Prodigy_Request_Maker;
use Prodigy\Includes\Frontend\Prodigy_Product_Template_Builder;
use Prodigy\Includes\Frontend\Prodigy_Product_Template_Item;
use Prodigy\Includes\Helpers\Prodigy_Formatting;
use Prodigy\Includes\Helpers\Prodigy_Template;
use Prodigy\includes\models\Prodigy_Order;
use Prodigy\Includes\Models\Prodigy_Products;
use Prodigy\Includes\Prodigy;
use Prodigy\Includes\Prodigy_Callback_Api_Listener;
use Prodigy\Includes\Prodigy_Cart;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Prodigy product page class
 *
 * @version    2.8.1
 * @package    prodigy/includes/public/pages
 */
class Prodigy_Product_Page extends Prodigy_Page {

	public const COUNT_COMMENTS_ON_PAGE_PRODUCT = 5;

	const SUBSCRIPTIONS_DISCOUNT_TYPE = 'percentage';

	const SUBSCRIPTIONS_DISCOUNT_SIGN = '%';

	/** @var Prodigy_Request_Maker */
	public Prodigy_Request_Maker $request_maker;

	/**
	 * @param  Prodigy_Order                 $order_model
	 * @param  Prodigy_Request_Maker         $request_maker
	 * @param  Prodigy_Cart                  $cart
	 * @param  Prodigy_Callback_Api_Listener $api_listener
	 *
	 * @throws \Exception
	 */
	public function __construct(
		Prodigy_Order $order_model,
		Prodigy_Request_Maker $request_maker,
		Prodigy_Cart $cart,
		Prodigy_Callback_Api_Listener $api_listener
	) {
		parent::__construct( $order_model, $request_maker, $cart, $api_listener );

		$this->request_maker = $request_maker;

		add_filter( 'pre_get_document_title', array( $this, 'prodigy_set_meta_tags' ) );
		add_action( 'wp_ajax_prodigy-public-get-variant-data', array( $this, 'prodigy_public_get_variant_data' ) );
		add_action(
			'wp_ajax_nopriv_prodigy-public-get-variant-data',
			array(
				$this,
				'prodigy_public_get_variant_data',
			)
		);
		add_action(
			'wp_ajax_prodigy-public-get-variant-multiple-data',
			array(
				$this,
				'prodigy_public_get_variant_multiple_data',
			)
		);
		add_action(
			'wp_ajax_nopriv_prodigy-public-get-variant-multiple-data',
			array(
				$this,
				'prodigy_public_get_variant_multiple_data',
			)
		);
		add_action( 'wp_ajax_prodigy-quick-edit', array( $this, 'prodigy_quick_view_get_product' ) );
		add_action( 'wp_ajax_nopriv_prodigy-quick-edit', array( $this, 'prodigy_quick_view_get_product' ) );
		add_action(
			'wp_ajax_prodigy-get-master-variant-data',
			array(
				$this,
				'prodigy_remote_get_master_variant_data',
			)
		);
		add_action(
			'wp_ajax_nopriv_prodigy-get-master-variant-data',
			array(
				$this,
				'prodigy_remote_get_master_variant_data',
			)
		);
		add_action( 'wp_ajax_prodigy-remote-get-inventory-product', array( $this, 'prodigy_get_inventory_product' ) );
		add_action(
			'wp_ajax_nopriv_prodigy-remote-get-inventory-product',
			array(
				$this,
				'prodigy_get_inventory_product',
			)
		);
		add_action( 'wp_ajax_prodigy-public-get-comments', array( $this, 'prodigy_get_comments' ) );
		add_action( 'wp_ajax_nopriv_prodigy-public-get-comments', array( $this, 'prodigy_get_comments' ) );
		add_action( 'wp_ajax_prodigy-public-get-comments-count', array( $this, 'prodigy_get_comments_count' ) );
		add_action( 'wp_ajax_nopriv_prodigy-public-get-comments-count', array( $this, 'prodigy_get_comments_count' ) );
		add_action( 'wp_ajax_prodigy-get-tiered-prices-range', array( $this, 'get_tiered_prices_range' ) );
		add_action( 'wp_ajax_nopriv_prodigy-get-tiered-prices-range', array( $this, 'get_tiered_prices_range' ) );
	}

	/**
	 * @return void
	 */
	public function get_tiered_prices_range(): void {
		if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'store-nonce' ) ) {
			return;
		}

		$product_id     = isset( $_POST['product_id'] ) ? sanitize_text_field( wp_unslash( $_POST['product_id'] ) ) : '';
		$product_object = $this->get_product_object( (int) $product_id );
		$range          = $product_object->get_tiered_price_range();
		$order_data     = $this->prodigy_get_order_data();
		if ( ! empty( $order_data ) ) {
			$is_product_already_enough_items = $this->is_already_enough_items( $product_id, $order_data, (int) $range['min_quantity'] );
			if ( $is_product_already_enough_items ) {
				$range['min_quantity'] = 1;
			}
		}

		wp_send_json_success( $range );
	}

	/**
	 * @param  int $product_id
	 *
	 * @return Prodigy_Product_Parser
	 */
	private function get_product_object( int $product_id ): Prodigy_Product_Parser {
		$product_data = $this->request_maker->do_product_request( $product_id );

		return new Prodigy_Product_Parser( $product_data );
	}

	/**
	 * @return array|null
	 */
	private function prodigy_get_order_data(): array {
		$response = array();
		if ( isset( $this->order_token ) ) {
			$response = Prodigy_Request_Maker::get_instance()->do_order_data_request( $this->order_token );
		}

		return $response;
	}

	/**
	 * @param  int   $product_id
	 * @param  array $order_data
	 * @param  int   $min_quantity
	 *
	 * @return bool
	 */
	private function is_already_enough_items( int $product_id, array $order_data, int $min_quantity ): bool {
		$total_quantity = 0;
		if ( isset( $order_data['included'] ) ) {
			foreach ( $order_data['included'] as $item ) {
				if ( isset( $item['attributes']['quantity'], $item['attributes']['product-id'] ) && $item['type'] === 'line-items' && $item['attributes']['product-id'] === $product_id ) {
					$total_quantity += (int) $item['attributes']['quantity'];
				}
			}
		}

		return $total_quantity >= $min_quantity;
	}

	/**
	 * set meta tags
	 */
	public function prodigy_set_meta_tags() {
		$slug    = get_queried_object()->post_name ?? '';
		$product = get_page_by_path( $slug, OBJECT, Prodigy::get_prodigy_product_type() );

		if ( isset( $product->ID ) ) {
			$title = get_post_meta( $product->ID, Prodigy_Products::PRODUCT_META_TITLE, true );
		}

		return $title ?? '';
	}

	/**
	 * Get inventory for product
	 */
	public function prodigy_get_inventory_product() {
		if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'store-nonce' ) ) {
			return;
		}
		$post_id        = isset( $_POST['post_id'] ) ? sanitize_text_field( wp_unslash( $_POST['post_id'] ) ) : '';
		$post_remote_id = isset( $_POST['remote_id'] ) ? sanitize_text_field( wp_unslash( $_POST['remote_id'] ) ) : '';

		if ( $post_id || $post_remote_id ) {
			$remote_id    = $post_remote_id ?? get_post_meta( (int) $post_id, Prodigy::PRODIGY_REMOTE_PRODUCT_ID, true );
			$product_info = '';
			if ( ! empty( $remote_id ) ) {
				$product_info = $this->request_maker->do_product_request( $remote_id, 'master-variant.inventory,variants.inventory' );
			}

			$attributes = array();

			if ( isset( $product_info->included ) ) {
				foreach ( $product_info->included as $item ) {
					if ( $item->type === 'inventories' ) {
						$attributes = $item->attributes;
					}
				}
			}

			wp_send_json_success( compact( 'attributes' ) );
		}
	}

	/**
	 * Get remote product by ajax and generate html
	 *
	 * @version 2.8.1
	 */
	public function prodigy_remote_get_master_variant_data() {
		if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'store-nonce' ) ) {
			return;
		}

		$post_id      = isset( $_POST['post_id'] ) ? sanitize_text_field( wp_unslash( $_POST['post_id'] ) ) : '';
		$items_number = isset( $_POST['items_number'] ) ? sanitize_text_field( wp_unslash( $_POST['items_number'] ) ) : '';

		$product_object                               = $this->get_product_object( (int) $post_id );
		$master_variant                               = $product_object->get_master_variant();
		$master_variant['subscriptions']              = $product_object->get_subscriptions( (int) $post_id );
		$master_variant['remote_main_price']          = $product_object->get_main_price();
		$master_variant['remote_master_variant_info'] = $product_object->get_variant_info( array(), $product_object->get_id_master_variant() );

		if ( $product_object->is_tiered_price() ) {
			$master_variant['tiered_price'] = $product_object->calculate_tiered_price( $master_variant, (int) ( $items_number ?? 1 ) );
		}

		wp_send_json_success( $master_variant );
	}

	/**
	 * @return void
	 */
	public function prodigy_get_comments_count() {
		$comm    = 0;
		$post_id = isset( $_POST['post_id'] ) ? sanitize_key( wp_unslash( $_POST['post_id'] ) ) : '';
		$page    = isset( $_POST['page'] ) ? sanitize_key( wp_unslash( $_POST['page'] ) ) : 1;

		if ( ! empty( $post_id ) ) {
			$comm = get_comments(
				array(
					'post_id' => $post_id,
					'count'   => true,
				)
			);
		}

		if ( ! empty( $comm ) ) {
			$count_p = ceil( $comm / self::COUNT_COMMENTS_ON_PAGE_PRODUCT );

			if ( $page > $count_p ) {
				$comm = 0;
			}
		}

		wp_send_json_success( $comm );
	}

	/**
	 * get pagination comments
	 */
	public function prodigy_get_comments() {
		if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'store-nonce' ) ) {
			return;
		}

		$post_id = isset( $_POST['post_id'] ) ? sanitize_key( wp_unslash( $_POST['post_id'] ) ) : '';
		$page    = isset( $_POST['page'] ) ? sanitize_key( wp_unslash( $_POST['page'] ) ) : 1;

		$page_num = max( 1, (int) $page );
		$comments = get_comments(
			array(
				'post_id' => (int) $post_id,
				'number'  => self::COUNT_COMMENTS_ON_PAGE_PRODUCT,
				'offset'  => ( $page_num - 1 ) * self::COUNT_COMMENTS_ON_PAGE_PRODUCT,
			)
		);

		$data_i = array(
			'callback' => 'prodigy_comments',
		);

		$data = wp_list_comments(
			$data_i,
			$comments
		);

		if ( ! empty( $data ) ) {
			echo wp_kses( $data, \Prodigy\Includes\Helpers\Prodigy_Formatting::get_allowed_html() );
		}

		wp_die();
	}

	/**
	 * Ajax handler for retrieving product variant data.
	 *
	 * @return void
	 */
	public function prodigy_public_get_variant_multiple_data(): void {
		if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'store-nonce' ) ) {
			wp_send_json_error( 'Unauthorised', 401 );
		}

		$post_data = filter_input_array(
			INPUT_POST,
			array(
				'attribute'       => FILTER_SANITIZE_SPECIAL_CHARS,
				'post_id'         => FILTER_VALIDATE_INT,
				'logo_id'         => FILTER_VALIDATE_INT,
				'location_id'     => FILTER_VALIDATE_INT,
				'bulk_attributes' => array(
					'filter' => FILTER_SANITIZE_SPECIAL_CHARS,
					'flags'  => FILTER_REQUIRE_ARRAY,
				),
				'variants'        => array(
					'filter' => FILTER_SANITIZE_SPECIAL_CHARS,
					'flags'  => FILTER_REQUIRE_ARRAY,
				),
			)
		);

		$variant_array     = array();
		$id_remote_product = $post_data['post_id'] ?? '';
		$bulk_attribute    = $post_data['bulk_attributes'] ?? array();
		$valid_variant     = $post_data['variants'] ?? array();

		if ( empty( $bulk_attribute ) || empty( $id_remote_product ) ) {
			wp_send_json_error( 'Invalid data', \WP_Http::BAD_REQUEST );
		}

		$product_obj = $this->get_product_object( (int) $id_remote_product );

		foreach ( $bulk_attribute as $item ) {
			$valid_variant[]                                   = $item['name'];
			$variant_array[ $item['name'] ]                    = $product_obj->get_variant_info( $valid_variant );
			$variant_array[ $item['name'] ]['is_tiered_price'] = $product_obj->is_tiered_price();
			$key = array_search( $item['name'], $valid_variant, true );
			unset( $valid_variant[ $key ] );
		}

		wp_send_json_success( $variant_array );
	}

	/**
	 * get remote variants
	 *
	 * @version 2.0.7
	 */
	public function prodigy_public_get_variant_data() {
		$nonce = sanitize_text_field( $_POST['nonce'] ?? '' );
		if ( ! $nonce || ! wp_verify_nonce( $nonce, 'store-nonce' ) ) {
			wp_send_json_error( 'Invalid nonce.' );

			return;
		}

		$is_bulk           = filter_var( $_POST['is_bulk'], FILTER_VALIDATE_BOOLEAN );
		$quantity          = filter_var( $_POST['number_of_items'], FILTER_VALIDATE_INT );
		$variants          = wp_unslash( $_POST['variants'] ?? array() );
		$id_remote_product = filter_var( wp_unslash( $_POST['post_id'] ?? '' ), FILTER_VALIDATE_INT );

		if ( $is_bulk ) {
			$variants = (array) $variants;
		} else {
			$variants = array( $variants );
		}

		$variant_data       = array();
		$product_data       = $this->request_maker->do_product_request( (int) $id_remote_product );
		$remote_product_obj = new Prodigy_Product_Parser( $product_data );

		if ( empty( $id_remote_product ) ) {
			wp_send_json_error( 'Not found product!', 404 );
		}

		foreach ( $variants as $key => $variant ) {
			if ( $is_bulk ) {
				if ( $remote_product_obj->is_tiered_price() ) {
					$quantity          = $this->get_bulk_quantity( $variants );
					$quantity_response = $variants[ $key ]['quantity'];
				} else {
					$quantity_response = $variant['quantity'];
				}
				$variant = explode( '&', $variant['variant'] );
			}
			$variant_data[ $key ] = $remote_product_obj->get_variant_info( $variant );

			if ( isset( $variant_data[ $key ]['remote_variant_id'] ) ) {
				$variant_data[ $key ]['subscriptions'] = $this->get_product_subscriptions( $remote_product_obj, $variant_data, $key );
			}

			if ( $remote_product_obj->is_tiered_price() ) {
				$variant_data[ $key ]['attributes']['tiered_price'] = $remote_product_obj->calculate_tiered_price( $variant_data[ $key ], (int) ( $quantity ?? 1 ) );
			}
			if ( $is_bulk ) {
				$variant_data[ $key ]['number_of_items'] = $quantity_response;
			}
			$variant_data[ $key ]['tiered_prices_range'] = $remote_product_obj->get_tiered_price_range();
		}

		wp_send_json_success( array( 'result' => $variant_data ) );
	}

	/**
	 * @param  array $items
	 *
	 * @return int
	 */
	private function get_bulk_quantity( array $items ): int {
		$total_quantity = 0;
		foreach ( $items as $item ) {
			if ( isset( $item['quantity'] ) && is_numeric( $item['quantity'] ) ) {
				$total_quantity += $item['quantity'];
			}
		}

		return (int) $total_quantity;
	}

	/**
	 * @param  Prodigy_Product_Parser $remote_product_obj
	 * @param  array                  $variant_data
	 * @param  string                 $key
	 *
	 * @return false|string
	 */
	private function get_product_subscriptions( Prodigy_Product_Parser $remote_product_obj, array $variant_data, string $key ) {
		$elementor_widget_data = get_option( 'elementor_prodigy_add_to_cart_widget_data' );
		$subscr_icon_type      = 'icon';
		$discount_sign         = self::SUBSCRIPTIONS_DISCOUNT_SIGN;
		$subscr_icon_class     = $elementor_widget_data['product_subscription_alert_icon']['value'] ?? 'icon icon-info';
		$subscr_svg_class      = 'icon-img';
		if ( isset( $elementor_widget_data['product_subscription_alert_icon_position'] ) && $elementor_widget_data['product_subscription_alert_icon_position'] === 'right' ) {
			$subscr_icon_class .= ' order-last';
			$subscr_svg_class  .= ' order-last';
		}

		$subscriptions      = $remote_product_obj->get_subscriptions( (int) $variant_data[ $key ]['remote_variant_id'] );
		$subscriptionPrices = $this->sort_subscription_prices( $variant_data[ $key ]['attributes']['subscription-prices'] ?? array() );

		$minimal_key = 0;
		if ( ! empty( $subscriptions ) ) {
			foreach ( $subscriptions as $key => $plan ) {
				if ( is_int( $key ) ) {
					if ( empty( $temp ) ) {
						$temp = (int) $plan['attributes']['subscription-price'];
					}
					if ( (int) $plan['attributes']['subscription-price'] < $temp ) {
						$temp        = (int) $plan['attributes']['subscription-price'];
						$minimal_key = $key;
					}
				}
			}

			if ( $subscriptions[ $minimal_key ]['attributes']['discount-type'] === self::SUBSCRIPTIONS_DISCOUNT_TYPE ) {
				$subscriptions['discount_sign'] = (int) $subscriptions[ $minimal_key ]['attributes']['discount-value'] . '%';
			} else {
				$subscriptions['discount_sign'] = get_option( 'pg_currency_type' ) . Prodigy_Formatting::prodigy_price_format( $subscriptions[ $minimal_key ]['attributes']['discount-value'] ) . '</span><span class="subscription-sale-currency-js">';
			}
		}

		return Prodigy_Template::prodigy_get_template_html(
			'single-product/subscriptions.php',
			array(
				'subscriptions'      => $subscriptions,
				'subscriptionPrices' => $subscriptionPrices,
				'minimal_key'        => $minimal_key,
				'subscr_icon_type'   => $subscr_icon_type,
				'discount_sign'      => $discount_sign,
			)
		);
	}

	/**
	 * @param  array $prices
	 *
	 * @return array
	 */
	protected function sort_subscription_prices( array $prices ): array {
		if ( empty( $prices ) ) {
			return array();
		}

		usort(
			$prices,
			static function ( $a, $b ) {
				return $a['condition_price'] > $b['condition_price'];
			}
		);

		foreach ( $prices as $price ) {
			$sortPrices[ $price['subscription_condition_id'] ] = (array) $price;
		}

		return $sortPrices ?? array();
	}

	/**
	 *  Get product for quick view modal window
	 */
	public function prodigy_quick_view_get_product(): void {
		if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'store-nonce' ) ) {
			wp_die( '', '', array( 'response' => 403 ) );
		}
		$id_remote_product = 0;
		if ( isset( $_POST['post_id'] ) ) {
			$id_remote_product = absint( $_POST['post_id'] );
		}
		if ( $id_remote_product <= 0 ) {
			wp_die( '', '', array( 'response' => 400 ) );
		}

		global $post;
		$post = get_post( $id_remote_product );
		if ( ! $post || Prodigy::get_prodigy_product_type() !== get_post_type( $post ) ) {
			wp_die( '', '', array( 'response' => 404 ) );
		}
		setup_postdata( $post );

		$product_template = new Prodigy_Product_Template_Builder( new Prodigy_Product_Template_Item() );
		$product_template->set_product( $id_remote_product );
		$GLOBALS['quick_view'] = true;

		$html = Prodigy_Template::prodigy_get_template_html( 'content-single-product.php' );
		wp_reset_postdata();
		wp_die( $html );
	}
}
