<?php
/**
 * The class that manage all.
 *
 * @package YITH WooCommerce Dynamic Pricing & Discounts\Classes\
 */


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

/**
 * This class manage all hook and load files.
 */
class YITH_WC_Dynamic_Pricing_Discounts {
	use YWDPD_Singleton_Trait;

	/**
	 * The construct, add hooks and load files.
	 *
	 * @author YITH <plugins@yithemes.com>
	 * @since  3.0.0
	 */
	private function __construct() {
		$this->includes();

		add_action( 'ywcrbp_premium_init', array( $this, 'disable_old_rolebased_integration' ), 99 );

		add_action( 'wp_loaded', array( $this, 'ywdpd_set_cron' ) );
		add_action( 'ywdpd_clean_cron', array( $this, 'clear_coupons' ) );
		add_action( 'woocommerce_checkout_create_order', array( $this, 'clear_ywdpd_coupon_after_create_order' ) );
	}

	/**
	 * Include all files.
	 *
	 * @since
	 */
	public function includes() {
		// Functions file.
		require_once YITH_YWDPD_INC . 'functions.yith-wc-dynamic-pricing-update.php';
		require_once YITH_YWDPD_INC . 'functions.yith-ywdpd-deprecated.php';
		require_once YITH_YWDPD_INC . 'functions.yith-wc-dynamic-options.php';
		require_once YITH_YWDPD_INC . 'functions.yith-wc-dynamic-pricing.php';

		// Traits .
		require_once YITH_YWDPD_INC . 'traits/trait-ywdpd-advanced-conditions-trait.php';
		require_once YITH_YWDPD_INC . 'traits/trait-ywdpd-cached-request-trait.php';

		// Data Stores.
		require_once YITH_YWDPD_INC . 'data-stores/class-ywdpd-exclusion-list-data-store.php';
		require_once YITH_YWDPD_INC . 'data-stores/class-ywdpd-dynamic-rules-data-store.php';
		// Support classes.
		require_once YITH_YWDPD_INC . 'class-yith-ywdpd-counter.php';
		require_once YITH_YWDPD_INC . 'class-yith-ywdpd-taxonomy.php';
		require_once YITH_YWDPD_INC . 'class-yith-wc-dynamic-pricing-options.php';
		require_once YITH_YWDPD_INC . 'class-ywdpd-utils.php';

		// Post Type registration.
		require_once YITH_YWDPD_INC . 'class-ywdpd-post-type.php';

		// Abstract classes.
		require_once YITH_YWDPD_INC . 'abstracts/abstract-ywdpd-data.php';
		require_once YITH_YWDPD_INC . 'abstracts/abstract-ywdpd-rule.php';
		require_once YITH_YWDPD_INC . 'abstracts/abstract-ywdpd-price-rule.php';

		// Price Rule classes.
		require_once YITH_YWDPD_INC . 'dynamic-rules/price-rules/class-ywdpd-quantity-table.php';
		require_once YITH_YWDPD_INC . 'dynamic-rules/price-rules/class-ywdpd-special-offer.php';
		require_once YITH_YWDPD_INC . 'dynamic-rules/price-rules/class-ywdpd-category-discount.php';
		require_once YITH_YWDPD_INC . 'dynamic-rules/price-rules/class-ywdpd-discount-whole.php';
		require_once YITH_YWDPD_INC . 'dynamic-rules/price-rules/class-ywdpd-gift-products.php';
		require_once YITH_YWDPD_INC . 'dynamic-rules/price-rules/class-ywdpd-bogo.php';
		require_once YITH_YWDPD_INC . 'dynamic-rules/price-rules/class-ywdpd-last-deals.php';
		require_once YITH_YWDPD_INC . '/legacy/class-ywdpd-exclude-items.php';

		// Cart rule class.
		require_once YITH_YWDPD_INC . 'dynamic-rules/cart-rules/class-ywdpd-cart-rule.php';

		// Price Rules Manager.
		require_once YITH_YWDPD_INC . 'class-yith-wc-dynamic-price-rules-manager.php';
		// Cart Rules Manager.
		require_once YITH_YWDPD_INC . 'class-yith-wc-dynamic-cart-rules-manager.php';
		// Gift rules manager.
		require_once YITH_YWDPD_INC . 'class-yith-wc-dynamic-pricing-gift-product.php';

		// Exclusion manager.
		require_once YITH_YWDPD_INC . 'class-yith-wc-dynamic-exclusion-manager.php';

		// Shortcodes.
		require_once YITH_YWDPD_INC . 'class-ywdpd-shortcodes.php';

		// Assets.
		require_once YITH_YWDPD_INC . 'class-ywdpd-assets.php';
		// Ajax.
		require_once YITH_YWDPD_INC . 'class-ywdpd-ajax.php';

		if ( defined( 'ELEMENTOR_VERSION' ) ) {
			// Elementor.
			require_once YITH_YWDPD_INC . '/integrations/elementor/class.yith-wc-dynamic-elementor.php';
		}
		// Legacy classes.
		require_once YITH_YWDPD_INC . '/legacy/class-yith-wc-dynamic-discounts.php';
		require_once YITH_YWDPD_INC . '/legacy/class-yith-wc-dynamic-pricing.php';
		require_once YITH_YWDPD_INC . '/legacy/class-yith-wc-dynamic-pricing-frontend.php';
		require_once YITH_YWDPD_INC . '/legacy/class-yith-wc-dynamic-pricing-helper.php';

		require_once YITH_YWDPD_INC . 'class-ywdpd-frontend.php';
		$this->get_frontend_manager();
		$this->get_exclusion_manager();
		// Integrations.
		require_once YITH_YWDPD_INC . '/integrations/class-yith-ywdpd-integrations.php';

		if ( self::is_request( 'admin' ) ) {
			require_once YITH_YWDPD_INC . 'admin/class-ywdpd-rules-table.php';
			require_once YITH_YWDPD_INC . 'admin/class-yith-wc-dynamic-pricing-admin.php';
		}

		if ( self::is_request( 'frontend' ) || self::is_request( 'ajax' ) ) {

			$this->get_gift_rules_manager();
			$this->get_price_rules_manager();
			$this->get_cart_rules_manager();
		}

		// Gutenberg.
		require_once YITH_YWDPD_INC . '/builders/class-ywdpd-builders.php';
		YWDPD_Builders::get_instance();

		// Scheduler.
		require_once YITH_YWDPD_INC . 'class-ywdpd-scheduler.php';

		require_once YITH_YWDPD_INC.'/wc-blocks/src/class-ywdpd-wc-blocks.php';

		YWDPD_WC_Blocks::get_instance();
	}

	/**
	 * What type of request is this?
	 *
	 * @param string $type admin, ajax, cron or frontend.
	 *
	 * @return bool
	 * @since  3.0.0
	 */
	public static function is_request( $type ) {
		$ajax_action = array(
			'woodmart_update_cart_item'
		);
		$current_action = isset( $_REQUEST['action'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['action'] ) ) : '';
		$is_ajax = in_array( $current_action, $ajax_action , true );
		switch ( $type ) {
			case 'admin':
				return is_admin() && ! defined( 'DOING_AJAX' ) || ( defined( 'DOING_AJAX' ) && DOING_AJAX && ( ! isset( $_REQUEST['context'] ) || ( isset( $_REQUEST['context'] ) && 'frontend' !== $_REQUEST['context'] ) ) ); //phpcs:ignore
			case 'ajax':
				return defined( 'DOING_AJAX' ) || $is_ajax;
			case 'frontend':
				return ( ! is_admin() || defined( 'DOING_AJAX' ) || $is_ajax ) && ! defined( 'DOING_CRON' );
		}

		return false;
	}


	/**
	 * Disable the old integration with YITH Role Based Prices
	 *
	 * @since  3.0.0
	 */
	public function disable_old_rolebased_integration() {
		add_filter( 'ywcrbp_init_dynamic_integration', '__return_false', 9999 );
	}

	/**
	 * Instance and return the gift product manager class
	 *
	 * @return YITH_WC_Dynamic_Pricing_Gift_Product
	 * @since  3.0.0
	 */
	public function get_gift_rules_manager() {
		return YITH_WC_Dynamic_Pricing_Gift_Product::get_instance();
	}

	/**
	 * Instance and return the price rules manager
	 *
	 * @return YWDPD_Price_Rules_Manager
	 * @since  3.0.0
	 */
	public function get_price_rules_manager() {
		return YWDPD_Price_Rules_Manager::get_instance();
	}

	/**
	 * Instance and return the cart rules manager
	 *
	 * @return YWDPD_Cart_Rules_Manager
	 * @since  3.0.0
	 */
	public function get_cart_rules_manager() {
		return YWDPD_Cart_Rules_Manager::get_instance();
	}

	/**
	 * Instance and return the frontend manager
	 *
	 * @return YWDPD_Frontend
	 * @since  3.0.0
	 */
	public function get_frontend_manager() {
		return YWDPD_Frontend::get_instance();
	}

	/**
	 * Instance and return the exclusion manager
	 *
	 * @return YITH_WC_Dynamic_Exclusion_Manager
	 * @since  3.0.0
	 */
	public function get_exclusion_manager() {
		return YITH_WC_Dynamic_Exclusion_Manager::get_instance();
	}


	/**
	 * Delete coupon after use it
	 *
	 * @param WC_Order $order The order.
	 *
	 * @throws Exception The exception.
	 */
	public function clear_ywdpd_coupon_after_create_order( $order ) {
		if ( version_compare( WC()->version, '3.7.0', '<' ) ) {
			$coupon_used = $order->get_used_coupons();
		} else {
			$coupon_used = $order->get_coupon_codes();
		}
		if ( $coupon_used ) {
			foreach ( $coupon_used as $coupons_code ) {
				$coupon   = new WC_Coupon( $coupons_code );
				$valid    = ywdpd_coupon_is_valid( $coupon, $order );
				$is_ywdpd = $coupon->get_meta( 'ywdpd_coupon', true );
				if ( $is_ywdpd && $valid ) {
					$coupon->delete();
				}
			}
		}
	}

	/**
	 * Clear coupons after use
	 *
	 * @since  1.0.0
	 */
	public function clear_coupons() {

		global $wpdb;
		$query   = "SELECT DISTINCT ( pm.post_id ) FROM {$wpdb->postmeta} AS pm WHERE pm.meta_key= %s AND pm.meta_value = %s ORDER BY pm.post_id DESC LIMIT 1000";
		$query   = $wpdb->prepare( $query, 'ywdpd_coupon', '1' ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
		$results = $wpdb->get_results( $query, ARRAY_A ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared

		$results = wp_list_pluck( $results, 'post_id' );

		$ids_to_remove = array();
		foreach ( $results as $result ) {
			$post_type = get_post_type( $result );
			$date_gmt  = get_post_datetime( $result, 'date', 'gmt' );

			/**
			 * APPLY_FILTERS: ywdpd_remove_coupon_older_than
			 *
			 * Change the day ago to delete older coupons.
			 *
			 * @param int $day_ago The day ago.
			 *
			 * @return int
			 */
			$day_ago = apply_filters( 'ywdpd_remove_coupon_older_than', strtotime( '-1 day', current_time( 'timestamp' ) ) ); // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested

			if ( 'shop_coupon' === $post_type && $date_gmt && $date_gmt->getTimestamp() < $day_ago ) {
				$ids_to_remove[] = $result;
			}
		}

		if ( count( $ids_to_remove ) > 0 ) {
			$non_cached_ids        = esc_sql( $ids_to_remove );
			$non_cached_ids_string = implode( ',', $non_cached_ids );
			$query                 = "DELETE FROM {$wpdb->postmeta} WHERE {$wpdb->postmeta}.post_id IN ( $non_cached_ids_string ); ";
			$wpdb->query( $query ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared
			$query = "DELETE FROM {$wpdb->posts} WHERE {$wpdb->posts}.ID IN ( $non_cached_ids_string );";
			$wpdb->query( $query ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared
		}

	}

	/**
	 * Set the cron to clear coupons
	 *
	 * @since  1.0.0
	 */
	public function ywdpd_set_cron() {
		if ( ! wp_next_scheduled( 'ywdpd_clean_cron' ) ) {
			$duration = apply_filters( 'ywdpd_set_cron_time', 'daily' );
			wp_schedule_event( time(), $duration, 'ywdpd_clean_cron' );
		}
	}
}

if ( ! function_exists( 'ywdpd_dynamic_pricing_discounts' ) ) {
	/**
	 * Return the unique instance of the class
	 */
	function ywdpd_dynamic_pricing_discounts() {

		return YITH_WC_Dynamic_Pricing_Discounts::get_instance();
	}
}
