<?php
namespace SabaiApps\Directories\Component\PaymentGateway\Controller;

use SabaiApps\Directories\Component\PaymentGateway\PaymentPlan;
use SabaiApps\Directories\Context;
use SabaiApps\Directories\Controller;

class VerifyDiscountCode extends Controller {

	protected function _doExecute( Context $context ) {
		// Must be an Ajax request
		if ( ! $context->getRequest()->isAjax() ) {
			$context->setBadRequestError();
			return;
		}

		// Check request token
		if ( ! $this->_checkToken( $context, 'paymentgateway_verify_discount_code', true ) ) {
			return;
		}

		// Get plan and discount bundle
		if ( ( ! $plan_id = $context->getRequest()->asInt( 'plan_id' ) )
			|| ( ! $plan = $this->Entity_Entity( 'post', $plan_id ) )
			|| $plan->getBundleType() !== 'paymentgateway_plan'
			|| ( ! $plan_bundle = $this->Entity_Bundle( $plan->getBundleName() ) )
			|| ( ! $discount_bundle = $this->Entity_Bundle( 'paymentgateway_discount', $plan_bundle->group ) )
		) {
			$context->setBadRequestError();
			return;
		}
		$plan = new PaymentPlan( $plan );

		// Validate new discount code if any
		$new_discount_info = null;
		if ( $new_discount_code = strtoupper( $context->getRequest()->asStr( 'discount_code' ) ) ) {
			if ( ( ! $discounts = $this->Entity_Query( 'post', $discount_bundle->name )->fieldIs( 'paymentgateway_discount', $new_discount_code, 'discount_code' )->fetch( 1 ) )
				|| ( ! $new_discount = array_shift( $discounts ) )
				|| ( ! $new_discount_info = $this->PaymentGateway_Util_isValidDiscount( $new_discount, $plan ) )
			) {
				$context->setError(
					sprintf(
						__( 'Invalid discount code: %s', 'directories-pro' ),
						$new_discount_code
					)
				);
				return;
			}
		}

		$action = $context->getRequest()->asStr( 'action', '' );
		if ( $entity_id = $context->getRequest()->asInt( 'entity_id' ) ) {
			if ( ( ! $entity = $this->Entity_Entity( 'post', $entity_id ) )
				|| ( ! $content_bundle = $this->Entity_Bundle( $entity->getBundleName() ) )
				|| $content_bundle->group !== $plan_bundle->group
			) {
				$context->setBadRequestError();
				return;
			}
			$fees = (array) $this->Payment_Fee_calculate( $entity, $plan, $action );
		} else {
			$fees = array();
		}
		$order_data = $this->PaymentGateway_Order_getData( $plan, $fees );

		$discount_codes = $context->getRequest()->asArray( 'discount_codes' );
		if ( ! empty( $order_data['discounts'] ) ) {
			foreach ( $order_data['discounts'] as $_discount_code ) {
				$discount_codes[] = $_discount_code['code'];
			}
		}
		if ( ! empty( $discount_codes )
			&& ( $discount_codes = array_filter( array_unique( $discount_codes ) ) )
		) {
			$discount_codes = array_map( 'strtoupper', $discount_codes );
			// Check if the discount code has already been applied
			if ( $new_discount_info ) {
				if ( in_array( $new_discount_info['discount_code'], $discount_codes, true ) ) {
					$context->setError( __( 'This discount code has already been applied.', 'directories-pro' ) );
					return;
				}
				if ( $new_discount_info['discount_type'] === 'percentage' ) {
					$context->setError(
						sprintf(
							__( 'The discount (%s) cannot be used together with any other discounts.', 'directories-pro' ),
							$new_discount_info['discount_code']
						)
					);
					return;
				}
			}

			foreach ( array_keys( $discount_codes ) as $i ) {
				if ( ( ! $d = $this->Entity_Query( 'post', $discount_bundle->name )->fieldIs( 'paymentgateway_discount', $discount_codes[ $i ], 'discount_code' )->fetch( 1 ) )
					|| ( ! $d = array_shift( $d ) )
					|| ( ! $discount_codes[ $i ] = $this->PaymentGateway_Util_isValidDiscount( $d, $plan ) )
				) {
					$context->setError( sprintf( __( 'Invalid discount code: %s', 'directories-pro' ), $discount_codes[ $i ] ) );
					return;
				}
				if ( $new_discount_info
					|| count( $discount_codes ) > 1
				) {
					if ( $discount_codes[ $i ]['discount_type'] === 'percentage' ) {
						$context->setError(
							sprintf(
								__( 'The discount (%s) cannot be used together with any other discounts.', 'directories-pro' ),
								$d->getTitle()
							)
						);
						return;
					}
				}
			}
		}

		// Calculate total
		$total = $order_data['price'];
		// Discount
		if ( $new_discount_info ) {
			if ( $new_discount_info['discount_type'] === 'percentage' ) {
				$discount_value = $total * $new_discount_info['discount_value'] / 100;
			} else {
				$discount_value = $new_discount_info['discount_value'];
				if ( ! empty( $discount_codes ) ) {
					foreach ( $discount_codes as $d ) {
						if ( $d['discount_type'] === 'fixed' ) {
							$discount_value += $d['discount_value'];
						}
					}
				}
			}
		} else {
			$discount_value = 0;
			foreach ( $discount_codes as $d ) {
				if ( $d['discount_type'] === 'fixed' ) {
					$discount_value += $d['discount_value'];
				}
			}
		}
		$total -= $discount_value;
		// Fees
		if ( ! empty( $order_data['fees'] ) ) {
			foreach ( array_keys( $order_data['fees'] ) as $fee_name ) {
				$fee = $order_data['fees'][ $fee_name ]['price'];
				if ( ! empty( $order_data['fees'][ $fee_name ]['is_discount'] ) ) {
					$fee *= -1;
				}
				$total += $fee;
			}
		}
		if ( $total < 0 ) {
			$total = 0;
		}
		// Tax
		$tax_amount = 0;
		if ( $total > 0
			&& ! empty( $order_data['tax'] )
		) {
			$tax_amount = $total * $order_data['tax'] / 100;
		}
		$total += $tax_amount;

		// Send success response
		$context->setSuccess(
			false,
			array(
				'total'              => html_entity_decode( $this->System_Currency_format( $total, $order_data['currency'] ), ENT_QUOTES, 'UTF-8' ),
				'tax_amount'         => html_entity_decode( $this->System_Currency_format( $tax_amount, $order_data['currency'] ), ENT_QUOTES, 'UTF-8' ),
				'discount_amount'    => html_entity_decode( $this->System_Currency_format( $discount_value, $order_data['currency'] ), ENT_QUOTES, 'UTF-8' ),
				'new_discount_label' => $new_discount ? $new_discount->getTitle() : null,
				'new_discount_code'  => $new_discount_info ? $new_discount_info['discount_code'] : null,
			)
		);
	}
}
