<?php
namespace SabaiApps\Directories\Component\WooCommerce\PaymentComponent;

use SabaiApps\Directories\Component\Entity\Type\IEntity;
use SabaiApps\Directories\Component\Payment;
use SabaiApps\Directories\Component\Payment\IOrder;
use SabaiApps\Directories\Component\Payment\ISubscription;
use SabaiApps\Directories\Component\Payment\IPlan;
use SabaiApps\Directories\Component\WooCommerce\PaymentPlan;
use SabaiApps\Directories\Component\WooCommerce\PaymentOrder;
use SabaiApps\Directories\Component\WooCommerce\PaymentSubscription;
use SabaiApps\Directories\Component\WooCommerce\IProduct;
use SabaiApps\Directories\Context;

class WooCommercePaymentComponent extends Payment\Component\AbstractComponent {

	protected function _paymentComponentInfo() {
		return array( 'label' => 'WooCommerce' );
	}

	public function paymentIsEnabled() {
		return $this->_application->getComponent( 'WooCommerce' )->isWooCommerceActive();
	}

	public function paymentIsGuestCheckoutEnabled() {
		return get_option( 'woocommerce_enable_guest_checkout' ) === 'yes';
	}

	public function paymentIsGuestSignupEnabled() {
		return get_option( 'woocommerce_enable_signup_and_login_from_checkout' ) === 'yes';
	}

	public function paymentIsGuestLoginEnabled() {
		return get_option( 'woocommerce_enable_checkout_login_reminder' ) === 'yes';
	}

	public function paymentGetCurrency() {
		return (string) get_woocommerce_currency();
	}

	public function paymentGetCurrencySymbol() {
		return (string) get_woocommerce_currency_symbol();
	}

	public function paymentGetPlanIds( $bundleName, $lang = null ) {
		global $wpdb;
		$base  = 'drts_' . $bundleName;
		$terms = array( $base );
		foreach ( array_keys( $this->_application->getComponent( 'WooCommerce' )->getProductTypes() ) as $product_type ) {
			if ( strpos( $product_type, $base . '__' ) === 0 ) {
				$terms[] = $product_type;
			}
		}
		if ( empty( $terms ) ) {
			return array();
		}

		if ( $this->_application->Filter( 'wooocmmerce_get_plan_ids_by_sql', false, array( $bundleName, $lang ) )
			|| ! function_exists( 'wc_get_products' )
		) {
			$term_ids = get_terms(
				array(
					'taxonomy' => 'product_type',
					'slug'     => $terms,
					'fields'   => 'ids',
				)
			);
			if ( is_wp_error( $term_ids ) ) {
				return array();
			}

			$ids = array();
			$sql = 'SELECT ' . $wpdb->prefix . 'posts.ID FROM ' . $wpdb->prefix . 'posts'
				. ' LEFT JOIN ' . $wpdb->prefix . 'term_relationships ON ' . $wpdb->prefix . 'posts.ID = ' . $wpdb->prefix . 'term_relationships.object_id'
				. ' WHERE ' . $wpdb->prefix . 'term_relationships.term_taxonomy_id IN (' . implode( ',', $term_ids ) . ') AND ' . $wpdb->prefix . 'posts.post_type = \'product\' AND ' . $wpdb->prefix . 'posts.post_status = \'publish\''
				. ' GROUP BY ' . $wpdb->prefix . 'posts.ID ORDER BY ' . $wpdb->prefix . 'posts.menu_order ASC';
			foreach ( $wpdb->get_results( $sql, ARRAY_N ) as $row ) {
				$ids[] = $row[0];
			}
		} else {
			$ids = wc_get_products(
				array(
					'return'           => 'ids',
					'type'             => $terms,
					'limit'            => -1,
					'orderby'          => 'menu_order',
					'order'            => 'ASC',
					'suppress_filters' => $lang === false ? true : false, // $lang === false for all languages
				)
			);
		}

		return $this->_application->Filter( 'woocommerce_payment_plan_ids', $ids, array( $bundleName, $lang ) );
	}

	public function paymentGetPlanById( $bundleName, $id ) {
		if ( ( ! $product = wc_get_product( $id ) )
			|| ! $product instanceof IProduct
		) {
			return;
		}

		return new PaymentPlan( $product );
	}

	public function paymentGetOrders( IEntity $entity, $limit = 0, $offset = 0 ) {
		global $wpdb;
		$entity_id   = $entity->getId();
		$order_items = $ret = array();
		$sql         = 'SELECT items.order_item_id, items.order_item_name, items.order_id, itemmeta2.meta_value AS action, itemmeta3.meta_value AS was_deactivated FROM ' . $wpdb->prefix . 'woocommerce_order_itemmeta itemmeta'
			. ' LEFT JOIN ' . $wpdb->prefix . 'woocommerce_order_items items ON itemmeta.order_item_id = items.order_item_id AND items.order_item_type = \'line_item\''
			. ' LEFT JOIN ' . $wpdb->prefix . 'woocommerce_order_itemmeta itemmeta2 ON itemmeta2.order_item_id = itemmeta.order_item_id AND itemmeta2.meta_key = \'_drts_action\''
			. ' LEFT JOIN ' . $wpdb->prefix . 'woocommerce_order_itemmeta itemmeta3 ON itemmeta3.order_item_id = itemmeta.order_item_id AND itemmeta3.meta_key = \'_drts_was_deactivated\''
			. ' WHERE itemmeta.meta_key = \'_drts_entity_id\' AND itemmeta.meta_value = %d ORDER BY order_id DESC';
		if ( ! empty( $limit ) ) {
			$sql  .= ' LIMIT %d, %d';
			$query = $wpdb->prepare( $sql, $entity_id, $offset, $limit );
		} else {
			// WPDB::prepare needs to be passed parameters exactly tne same number of placeholders
			$query = $wpdb->prepare( $sql, $entity_id );
		}
		foreach ( $wpdb->get_results( $query, ARRAY_N ) as $row ) {
			$order_items[ $row[2] ][ $row[0] ] = array(
				$row[1],
				array(
					'action'          => $row[3],
					'was_deactivated' => ! empty( $row[4] ),
				),
			);
		}
		if ( ! empty( $order_items ) ) {
			foreach ( $order_items as $order_id => $_order_items ) {
				if ( ( ! $order = wc_get_order( $order_id ) )
					|| $order->get_type() !== 'shop_order'
				) {
					continue;
				}

				foreach ( $_order_items as $item_id => $item ) {
					$ret[] = new PaymentOrder( $order, $item_id, $item[0], $item[1], $entity_id, $entity->getType() );
				}
			}
		}

		return $ret;
	}

	public function paymentGetOrderById( $orderItemId = null ) {
		if ( ( $order_id = wc_get_order_id_by_order_item_id( $orderItemId ) )
			&& ( $order = wc_get_order( $order_id ) )
		) {
			foreach ( $order->get_items() as $item_id => $item ) {
				if ( $item_id == $orderItemId ) {
					return new PaymentOrder(
						$order,
						$item_id,
						$item->get_name(),
						array(
							'action'          => $item->get_meta( '_drts_action' ),
							'was_deactivated' => $item->get_meta( '_drts_was_deactivated' ) ? true : false,
						),
						$item->get_meta( '_drts_entity_id' ),
						$item->get_meta( '_drts_entity_type' )
					);
				}
			}
		}
	}

	public function paymentGetUserOrders( $userId, $limit = 0, $offset = 0 ) {
		global $wpdb;
		$order_items = $ret = array();
		if ( $this->_isHposEnabled() ) {
			$sql = 'SELECT items.order_item_id, items.order_item_name, items.order_id, meta.meta_value AS action, meta2.meta_value AS entity_id, meta3.meta_value AS entity_type, meta4.meta_value AS was_deactivated'
				. ' FROM ' . $wpdb->prefix . 'woocommerce_order_itemmeta meta'
				. ' INNER JOIN ' . $wpdb->prefix . 'woocommerce_order_items items ON meta.order_item_id = items.order_item_id'
				. ' AND items.order_item_type = \'line_item\''
				. ' INNER JOIN ' . $wpdb->prefix . 'wc_orders orders ON orders.id = items.order_id'
				. ' INNER JOIN ' . $wpdb->prefix . 'woocommerce_order_itemmeta meta2 ON meta2.order_item_id = meta.order_item_id'
				. ' AND meta2.meta_key = \'_drts_entity_id\''
				. ' INNER JOIN ' . $wpdb->prefix . 'woocommerce_order_itemmeta meta3 ON meta3.order_item_id = meta.order_item_id'
				. ' AND meta3.meta_key = \'_drts_entity_type\''
				. ' LEFT JOIN ' . $wpdb->prefix . 'woocommerce_order_itemmeta meta4 ON meta4.order_item_id = meta.order_item_id'
				. ' AND meta4.meta_key = \'_drts_was_deactivated\''
				. ' WHERE meta.meta_key = \'_drts_action\''
				. ' AND orders.type= \'shop_order\''
				. ' AND orders.customer_id = %d'
				. ' AND orders.status != \'trash\''
				. ' AND orders.parent_order_id = 0'
				. ' ORDER BY order_id DESC';
		} else {
			$sql = 'SELECT items.order_item_id, items.order_item_name, items.order_id, itemmeta.meta_value AS action, itemmeta2.meta_value AS entity_id, itemmeta3.meta_value AS was_deactivated'
				. ' FROM ' . $wpdb->prefix . 'woocommerce_order_itemmeta itemmeta'
				. ' INNER JOIN ' . $wpdb->prefix . 'woocommerce_order_items items ON itemmeta.order_item_id = items.order_item_id'
				. ' AND items.order_item_type = \'line_item\''
				. ' INNER JOIN ' . $wpdb->prefix . 'posts posts ON posts.ID = items.order_id'
				. ' INNER JOIN ' . $wpdb->prefix . 'postmeta postmeta ON postmeta.post_id = posts.ID'
				. ' INNER JOIN ' . $wpdb->prefix . 'woocommerce_order_itemmeta itemmeta2 ON itemmeta2.order_item_id = itemmeta.order_item_id'
				. ' AND itemmeta2.meta_key = \'_drts_entity_id\''
				. ' LEFT JOIN ' . $wpdb->prefix . 'woocommerce_order_itemmeta itemmeta3 ON itemmeta3.order_item_id = itemmeta.order_item_id'
				. ' AND itemmeta3.meta_key = \'_drts_was_deactivated\''
				. ' WHERE itemmeta.meta_key = \'_drts_action\''
				. ' AND posts.post_parent = 0'
				. ' AND postmeta.meta_key = \'_customer_user\' AND postmeta.meta_value = %d'
				. ' ORDER BY order_id DESC';
		}
		if ( ! empty( $limit ) ) {
			$sql .= ' LIMIT %d, %d';
		}
		$query = $wpdb->prepare( $sql, $userId, $offset, $limit );
		foreach ( $wpdb->get_results( $query, ARRAY_N ) as $row ) {
			$order_items[ $row[2] ][ $row[0] ] = array(
				$row[1],
				array(
					'action'          => $row[3],
					'was_deactivated' => ! empty( $row[6] ),
				),
				$row[4],
				$row[5],
			);
		}
		if ( ! empty( $order_items ) ) {
			foreach ( $order_items as $order_id => $_order_items ) {
				if ( ! $order = wc_get_order( $order_id ) ) {
					continue;
				}

				foreach ( $_order_items as $item_id => $item ) {
					$ret[] = new PaymentOrder( $order, $item_id, $item[0], $item[1], $item[2], $item[3] );
				}
			}
		}

		return $ret;
	}

	public function paymentCountUserOrders( $userId ) {
		global $wpdb;
		if ( $this->_isHposEnabled() ) {
			$sql = 'SELECT COUNT(*) FROM ' . $wpdb->prefix . 'woocommerce_order_itemmeta itemmeta'
				. ' INNER JOIN ' . $wpdb->prefix . 'woocommerce_order_items items ON itemmeta.order_item_id = items.order_item_id'
				. ' AND items.order_item_type = \'line_item\''
				. ' INNER JOIN ' . $wpdb->prefix . 'wc_orders orders ON orders.id = items.order_id'
				. ' WHERE itemmeta.meta_key = \'_drts_action\''
				. ' AND orders.type= \'shop_order\' AND orders.customer_id = %d AND orders.status != \'trash\' AND orders.parent_order_id = 0';
		} else {
			$sql = 'SELECT COUNT(*) FROM ' . $wpdb->prefix . 'woocommerce_order_itemmeta itemmeta'
				. ' INNER JOIN ' . $wpdb->prefix . 'woocommerce_order_items items ON itemmeta.order_item_id = items.order_item_id'
				. ' AND items.order_item_type = \'line_item\''
				. ' INNER JOIN ' . $wpdb->prefix . 'posts posts ON posts.ID = items.order_id'
				. ' INNER JOIN ' . $wpdb->prefix . 'postmeta postmeta ON postmeta.post_id = posts.ID'
				. ' WHERE itemmeta.meta_key = \'_drts_action\' AND posts.post_parent = 0 AND postmeta.meta_key = \'_customer_user\' AND postmeta.meta_value = %d';
		}
		return $wpdb->get_var( $wpdb->prepare( $sql, $userId ) );
	}

	public function paymentHasPendingOrder( IEntity $entity, array $actions ) {
		if ( $this->_application->getPlatform()->isTranslatable( $entity->getType(), $entity->getBundleName() ) ) {
			// Include orders for translated entities
			$entity_ids = $this->_application->Entity_Translations_ids( $entity );
		} else {
			$entity_ids = array();
		}
		$entity_ids[] = $entity->getId();
		$db           = $this->_application->getDB();
		$statuses     = array(
			'wc-completed',
			'wc-refunded',
			'wc-cancelled',
			'wc-failed',
			'trash',
			'wc-expired',
			'wc-active', // WC Subscriptions
		);
		$sql          = sprintf(
			'
            SELECT COUNT(*) FROM %1$sposts posts
              LEFT JOIN %1$swoocommerce_order_items item ON item.order_id = posts.ID
              LEFT JOIN %1$swoocommerce_order_itemmeta meta1 ON meta1.order_item_id = item.order_item_id
              LEFT JOIN %1$swoocommerce_order_itemmeta meta2 ON meta2.order_item_id = item.order_item_id
              WHERE posts.post_status NOT IN (%2$s)
                AND meta1.meta_key = \'_drts_entity_id\' AND meta1.meta_value IN (%2$s)
                AND meta2.meta_key = \'_drts_action\' AND meta2.meta_value IN (%3$s)',
			$GLOBALS['wpdb']->prefix,
			implode( ',', array_map( array( $db, 'escapeString' ), $statuses ) ),
			implode( ',', $entity_ids ),
			implode( ',', array_map( array( $db, 'escapeString' ), $actions ) )
		);

		return $this->_application->getDB()->query( $sql )->fetchSingle() > 0;
	}

	protected function _isHposEnabled() {
		return is_callable( '\Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled' )
			&& \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled();
	}

	public function paymentCheckoutForm( Context $context, $planOrOrder, ?IEntity $entity = null, $action = null ) {
		$plan = $planOrOrder instanceof IOrder ? $planOrOrder->paymentOrderPlan() : $planOrOrder;
		if ( ! $this->_application->Payment_Plan_isCheckoutRequired( $plan, $user_id = $entity->getAuthorId() ) ) {
			// Manually create order and process
			$order = wc_create_order( array( 'status' => 'pending' ) );
			$order->set_customer_id( $user_id );
			$item_id = $order->add_product( $plan->getProduct(), 1 );
			if ( ! $item = $order->get_item( $item_id, false ) ) {
				throw new Exception\RuntimeException( 'Failed fetching order item for free payment plan.' );
			}
			// Add required order item meta data
			foreach ( $this->_getOrderItemMeta( $entity, $action ) as $meta_key => $meta_value ) {
				$item->add_meta_data( $meta_key, $meta_value );
			}
			// Set billing address
			$user_meta = get_user_meta( $user_id );
			$address   = array();
			foreach ( array( 'first_name', 'last_name', 'email', 'phone', 'address_1', 'address_2', 'city', 'state', 'postcode', 'country' ) as $addr_field ) {
				$address[ $addr_field ] = isset( $user_meta[ 'billing_' . $addr_field ][0] ) ? $user_meta[ 'billing_' . $addr_field ][0] : '';
			}
			$order->set_address( $address, 'billing' );
			$order->calculate_totals();

			// Update entity status
			if ( ! $entity->isPublished()
				&& ! $entity->isPending()
			) {
				$this->_application->Entity_Save(
					$entity,
					array(
						'status' => $this->_application->Entity_Status( $entity->getType(), 'pending' ),
					)
				);
			}

			try {
				// Create features
				$this->_application->Payment_Features_create( $entity, $plan, $item_id );
			} catch ( Exception\IException $e ) {
				$this->_application->logError( 'Failed creating features for entity. Entity type: ' . $entity->getType() . '; Entity ID: ' . $entity->getId() . '; Order item ID: ' . $item->get_id() );
			}

			// Mark order completed
			if ( ! $order->update_status( 'completed', 'Order for free payment plan completed manually.', true ) ) {
				throw new Exception\RuntimeException( 'Error updating order status to completed for free payment plan.' );
			}
		}

		return array();
	}

	public function paymentCheckoutComplete( Context $context, Payment\IPlan $plan, IEntity $entity, $action ) {
		if ( ! $this->_application->Payment_Plan_isCheckoutRequired( $plan, $entity->getAuthorId() ) ) {
			return;
		}

		// Remove from cart if already added
		if ( $cart_item_key = $this->_isEntityInCart( $entity ) ) {
			WC()->cart->remove_cart_item( $cart_item_key );
		}

		// Add to cart
		WC()->cart->add_to_cart(
			$plan->paymentPlanId(),
			1, // quantity
			0, // variation ID
			array(), // variation attributes
			$this->_getOrderItemMeta( $entity, $action )
		);

		// Redirect to cart or checkout page
		$settings = $this->getSettings();
		$context->setRedirect( empty( $settings['bypass_cart'] ) ? wc_get_cart_url() : wc_get_checkout_url() );
	}

	protected function _getOrderItemMeta( IEntity $entity, $action ) {
		$order_item_meta = array(
			'_drts_action'      => $action,
			'_drts_entity_id'   => $entity->getId(),
			'_drts_entity_type' => $entity->getType(),
			'drts_post_id'      => $entity->getId(), // for displaying order details
		);
		if ( $action === 'submit' ) {
			$was_deactivated                          = $entity->getSingleFieldValue( 'payment_plan', 'deactivated_at' ) ? 1 : 0;
			$order_item_meta['_drts_was_deactivated'] = $was_deactivated;
			$order_item_meta['drts_action']           = $this->_application->Payment_Util_actionLabel( $action, $was_deactivated );  // for displaying order details
		} else {
			$order_item_meta['drts_action'] = $this->_application->Payment_Util_actionLabel( $action ); // for displaying order details
		}
		return $order_item_meta;
	}

	public function paymentCheckoutBtnText( $bundleName, $action, $planId = null ) {
		$settings = $this->getSettings();
		if ( empty( $settings['bypass_cart'] ) ) {
			return __( 'Add to cart', 'directories-pro' );
		}
	}

	public function paymentIsSubscriptionEnabled() {
		return $this->_application->getComponent( 'WooCommerce' )->isWCSActive();
	}

	public function paymentGetSubscriptionById( $subscriptionId ) {
		return $this->_application->getComponent( 'WooCommerce' )->getPaymentSubscription( $subscriptionId );
	}

	public function paymentGetSubscriptions( IEntity $entity, $limit = 0, $offset = 0 ) {
		global $wpdb;
		$order_items = $ret = array();
		$sql         = 'SELECT items.order_item_id, items.order_item_name, items.order_id'
			. ' FROM ' . $wpdb->prefix . 'woocommerce_order_itemmeta itemmeta'
			. ' INNER JOIN ' . $wpdb->prefix . 'woocommerce_order_items items ON itemmeta.order_item_id = items.order_item_id'
			. ' AND items.order_item_type = \'line_item\''
			. ' INNER JOIN ' . $wpdb->prefix . 'posts posts ON posts.ID = items.order_id'
			. ' WHERE itemmeta.meta_key = \'_drts_entity_id\' AND itemmeta.meta_value = %d'
			. ' AND posts.post_type = \'shop_subscription\''
			. ' ORDER BY order_id DESC';
		if ( ! empty( $limit ) ) {
			$sql  .= ' LIMIT %d, %d';
			$query = $wpdb->prepare( $sql, $entity->getId(), $offset, $limit );
		} else {
			$query = $wpdb->prepare( $sql, $entity->getId() );
		}
		foreach ( $wpdb->get_results( $query, ARRAY_N ) as $row ) {
			$order_items[ $row[2] ][ $row[0] ] = $row[1];
		}
		if ( ! empty( $order_items ) ) {
			foreach ( $order_items as $order_id => $_order_items ) {
				$subscription = wcs_get_subscription( $order_id );
				foreach ( $_order_items as $item_id => $item_name ) {
					$ret[] = new PaymentSubscription( $subscription, $item_id, $item_name, $entity->getId(), $entity->getType() );
				}
			}
		}

		return $ret;
	}

	public function paymentGetUserSubscriptions( $userId, $limit = 0, $offset = 0 ) {
		global $wpdb;
		$order_items = $ret = array();
		if ( $this->_isHposEnabled() ) {
			$sql = 'SELECT items.order_item_id, items.order_item_name, items.order_id, meta2.meta_value AS entity_id, meta3.meta_value AS entity_type'
				. ' FROM ' . $wpdb->prefix . 'woocommerce_order_itemmeta meta'
				. ' INNER JOIN ' . $wpdb->prefix . 'woocommerce_order_items items ON meta.order_item_id = items.order_item_id'
				. ' AND items.order_item_type = \'line_item\''
				. ' INNER JOIN ' . $wpdb->prefix . 'wc_orders orders ON orders.id = items.order_id'
				. ' INNER JOIN ' . $wpdb->prefix . 'woocommerce_order_itemmeta meta2 ON meta2.order_item_id = meta.order_item_id'
				. ' AND meta2.meta_key = \'_drts_entity_id\''
				. ' INNER JOIN ' . $wpdb->prefix . 'woocommerce_order_itemmeta meta3 ON meta3.order_item_id = meta.order_item_id'
				. ' AND meta3.meta_key = \'_drts_entity_type\''
				. ' WHERE meta.meta_key = \'_drts_action\''
				. ' AND orders.type= \'shop_subscription\''
				. ' AND orders.customer_id = %d'
				. ' AND orders.status != \'trash\''
				. ' AND orders.parent_order_id != 0'
				. ' ORDER BY order_id DESC';
		} else {
			$sql = 'SELECT items.order_item_id, items.order_item_name, items.order_id, itemmeta2.meta_value AS entity_id'
				. ' FROM ' . $wpdb->prefix . 'woocommerce_order_itemmeta itemmeta'
				. ' INNER JOIN ' . $wpdb->prefix . 'woocommerce_order_items items ON itemmeta.order_item_id = items.order_item_id'
				. ' AND items.order_item_type = \'line_item\''
				. ' INNER JOIN ' . $wpdb->prefix . 'posts posts ON posts.ID = items.order_id'
				. ' INNER JOIN ' . $wpdb->prefix . 'postmeta postmeta ON postmeta.post_id = posts.ID'
				. ' INNER JOIN ' . $wpdb->prefix . 'woocommerce_order_itemmeta itemmeta2 ON itemmeta2.order_item_id = itemmeta.order_item_id'
				. ' AND itemmeta2.meta_key = \'_drts_entity_id\''
				. ' WHERE itemmeta.meta_key = \'_drts_action\''
				. ' AND posts.post_parent != 0'
				. ' AND postmeta.meta_key = \'_customer_user\' AND postmeta.meta_value = %d'
				. ' ORDER BY order_id DESC';
		}
		if ( ! empty( $limit ) ) {
			$sql  .= ' LIMIT %d, %d';
			$query = $wpdb->prepare( $sql, $userId, $offset, $limit );
		} else {
			$query = $wpdb->prepare( $sql, $userId );
		}
		foreach ( $wpdb->get_results( $query, ARRAY_N ) as $row ) {
			$order_items[ $row[2] ][ $row[0] ] = array( $row[1], $row[3], $row[4] );
		}
		if ( ! empty( $order_items ) ) {
			foreach ( $order_items as $order_id => $_order_items ) {
				$subscription = wcs_get_subscription( $order_id );
				foreach ( $_order_items as $item_id => $item ) {
					$ret[] = new PaymentSubscription( $subscription, $item_id, $item[0], $item[1], $item[2] );
				}
			}
		}

		return $ret;
	}

	public function paymentCountUserSubscriptions( $userId ) {
		global $wpdb;
		if ( $this->_isHposEnabled() ) {
			$sql = 'SELECT COUNT(*) FROM ' . $wpdb->prefix . 'woocommerce_order_itemmeta itemmeta'
				. ' INNER JOIN ' . $wpdb->prefix . 'woocommerce_order_items items ON itemmeta.order_item_id = items.order_item_id'
				. ' AND items.order_item_type = \'line_item\''
				. ' INNER JOIN ' . $wpdb->prefix . 'wc_orders orders ON orders.id = items.order_id'
				. ' WHERE itemmeta.meta_key = \'_drts_action\''
				. ' AND orders.type= \'shop_subscription\' AND orders.customer_id = %d AND orders.status != \'trash\' AND orders.parent_order_id != 0';
		} else {
			$sql = 'SELECT COUNT(*) FROM ' . $wpdb->prefix . 'woocommerce_order_itemmeta itemmeta'
				. ' INNER JOIN ' . $wpdb->prefix . 'woocommerce_order_items items ON itemmeta.order_item_id = items.order_item_id'
				. ' AND items.order_item_type = \'line_item\''
				. ' INNER JOIN ' . $wpdb->prefix . 'posts posts ON posts.ID = items.order_id'
				. ' INNER JOIN ' . $wpdb->prefix . 'postmeta postmeta ON postmeta.post_id = posts.ID'
				. ' WHERE itemmeta.meta_key = \'_drts_action\' AND posts.post_parent != 0 AND postmeta.meta_key = \'_customer_user\' AND postmeta.meta_value = %d';
		}
		return $wpdb->get_var( $wpdb->prepare( $sql, $userId ) );
	}

	public function paymentGetClaimOrderId( IEntity $claim, IEntity $claimedEntity ) {
		global $wpdb;
		$sql = 'SELECT items.order_item_id FROM ' . $wpdb->prefix . 'woocommerce_order_itemmeta itemmeta'
			. ' LEFT JOIN ' . $wpdb->prefix . 'woocommerce_order_items items ON itemmeta.order_item_id = items.order_item_id AND items.order_item_type = \'line_item\''
			. ' WHERE itemmeta.meta_key = \'_drts_entity_id\' AND itemmeta.meta_value = %d';
		return $wpdb->get_var( $wpdb->prepare( $sql, $claim->getId() ) );
	}

	public function paymentRefundOrder( $orderId, $reason = '' ) {
		$this->_application->WooCommerce_RefundOrder( $orderId, $reason );
	}

	public function paymentGetPlanId( $bundleName, $planId, $lang ) {
		return $this->_application->getPlatform()->getTranslatedId( 'post', 'product', $planId, $lang );
	}

	public function paymentFormatPlanPrice( Payment\IPlan $plan, $includeTax = true ) {
		// Remove unwanted zero from price html
		add_filter( 'woocommerce_price_trim_zeros', '__return_true', 99999 );
		$product = $plan->getProduct();
		if ( '' === $product->get_price() ) {
			$price = apply_filters( 'woocommerce_empty_price_html', '', $product );
		} else {
			$func  = $includeTax ? 'wc_get_price_including_tax' : 'wc_get_price_excluding_tax';
			$price = $func( $product );
			if ( $product->is_on_sale() ) {
				$price = wc_format_sale_price( $func( $product, array( 'price' => $product->get_regular_price() ) ), $price );
			} else {
				$price = wc_price( $price );
			}
			$price .= $product->get_price_suffix();
		}
		$html = apply_filters( 'woocommerce_get_price_html', $price, $product );
		// Remove filter added
		remove_filter( 'woocommerce_price_trim_zeros', '__return_true', 99999 );

		return $html;
	}

	public function paymentSettingsForm( array $settings, array $parents ) {
		$form = array(
			'bypass_cart' => array(
				'#type'          => 'checkbox',
				'#title'         => __( 'Skip cart page', 'directories-pro' ),
				'#default_value' => ! empty( $settings['bypass_cart'] ),
				'#horizontal'    => true,
			),
		);
		if ( $this->_application->getComponent( 'WooCommerce' )->isWCMActive() ) {
			$form['memberships'] = array(
				'expire' => array(
					'#type'          => 'checkbox',
					'#title'         => __( 'Expire payment plans when WooCommerce Memberships membership becomes inactive', 'directories-pro' ),
					'#default_value' => ! empty( $settings['memberships']['expire'] ),
					'#horizontal'    => true,
				),
			);
		}

		return $form;
	}

	public function paymentGetOrderDetailHtml( IOrder $order ) {
		ob_start();
		echo '<div class="woocommerce">';
		wc_get_template(
			'myaccount/view-order.php',
			array(
				'order'    => $order->getOrder(),
				'order_id' => $order->getOrder()->get_id(),
			)
		);
		echo '</div>';

		return ob_get_clean();
	}

	public function paymentGetSubscriptionDetailHtml( ISubscription $subscription ) {
		ob_start();
		echo '<div class="woocommerce">';
		\WCS_Template_Loader::get_subscription_details_template( $subscription->getSubscription() );
		\WCS_Template_Loader::get_subscription_totals_template( $subscription->getSubscription() );
		echo '</div>';

		return ob_get_clean();
	}

	protected function _isEntityInCart( IEntity $entity ) {
		foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
			if ( $values['data'] instanceof IProduct
				&& isset( $values['_drts_entity_id'] )
				&& $values['_drts_entity_id'] === $entity->getId()
			) {
				return $cart_item_key;
			}
		}
		return false;
	}

	public function paymentGetPlanContentBundleName( IPlan $plan ) {
		$plan_type = $plan->paymentPlanType();
		$product   = $plan->getProduct();
		return $plan_type === 'base' ?
			substr( $product->get_type(), strlen( 'drts_' ) ) : // remove prefix
			substr( $product->get_type(), strlen( 'drts_' ), -1 * ( strlen( $plan_type ) + 2 ) ); // remove prefix and "__{$plan_type}" suffix
	}

	public function paymentPlanHasDiscount( IPlan $plan ) {
		return $plan->getProduct()->is_on_sale();
	}
}
