<?php
namespace Payplug\PayplugWoocommerce\Front;

use Payplug\Payplug;
use Payplug\PayplugWoocommerce\Controller\ApplePay as ApplePayGateway;
use Payplug\PayplugWoocommerce\Gateway\PayplugAddressData;
use Payplug\PayplugWoocommerce\PayplugWoocommerceHelper;
use function is_cart;

class ApplePay {

	public function __construct() {

		//routes for apple_pay on cart and product page
		add_action( 'wc_ajax_applepay_get_shippings', [ $this, 'applepay_get_shippings' ] );
		add_action( 'wc_ajax_place_order_with_dummy_data', [ $this, 'place_order_with_dummy_data' ] );
		add_action( 'wc_ajax_update_applepay_order', [ $this, 'update_applepay_order' ] );
		add_action( 'wc_ajax_update_applepay_payment', [ $this, 'update_applepay_payment' ] );
		add_action( 'wc_ajax_applepay_cancel_order', [ $this, 'applepay_cancel_order' ] );
		add_action( 'wc_ajax_applepay_empty_cart', [ $this, 'applepay_empty_cart' ] );
		add_action( 'wc_ajax_applepay_add_to_cart', [ $this, 'applepay_add_to_cart' ] );
	}

	public function applepay_get_shippings() {
		WC()->customer->set_shipping_country('FR');
		WC()->customer->set_shipping_city('Paris');
		WC()->customer->set_shipping_postcode('12345');
		WC()->customer->set_shipping_address('Dummy Address');

		$packages = WC()->cart->get_shipping_packages();
		$shippings = [];

		foreach ( $packages as $package_key => $package ) {
			$shipping_methods = $this->get_shipping_methods_from_package($package);

			foreach ( $shipping_methods as $shipping_method ) {

				if (!$shipping_method->supports('shipping-zones') || !$shipping_method->is_enabled()) {
					continue;
				}

				$rates = $shipping_method->get_rates_for_package($package);
				if($this->checkApplePayShipping($shipping_method)){
					$shipping_rate = $rates[$shipping_method->get_rate_id()];

					array_push($shippings, [
						'identifier' => $shipping_method->id.'_'.$shipping_method->instance_id,
						'label' => $shipping_method->method_title,
						'detail' => strip_tags($shipping_method->method_description),
						'amount' =>$shipping_rate->get_cost()+$shipping_rate->get_shipping_tax()
					]);
				}
			}
		}
		wp_send_json_success($shippings);
	}

	/**
	 * @param $shipping
	 * @return bool
	 */
	private function checkApplePayShipping($shipping = []){
		if(empty($shipping)){
			return false;
		}

		$apple_pay_options = PayplugWoocommerceHelper::get_applepay_options();
		$apple_pay_carriers = $apple_pay_options['carriers'];

		$exists = false;
		foreach($apple_pay_carriers as $carrier => $carrier_id){
			if($carrier_id === $shipping->id){
				return true;
			}
		}

		return $exists;
	}


	private function get_shipping_methods_from_package($package){
		$shipping_zone = \WC_Shipping_Zones::get_zone_matching_package( $package );
		return $shipping_zone->get_shipping_methods( true );
	}

	public function place_order_with_dummy_data() {
		$apple_pay = new ApplePayGateway();
		if ( is_admin() ) {
			return;
		}

		$cart = WC()->cart;

		if ( ! $cart->is_empty() ) {
			try{
				$checkout = WC()->checkout();

				$order_id = $checkout->create_order(array('payment_method' => $apple_pay->id));
				$order = wc_get_order($order_id);


				$order->set_address( [
					'first_name' => 'payplug_applepay_first_name',
					'last_name'  => 'payplug_applepay_last_name',
					'address_1'  => 'payplug_applepay_address',
					'address_2'  => '',
					'city'       => 'payplug_applepay_city',
					'postcode'   => 'payplug_applepay_psotcode',
					'country'    => WC()->countries->get_base_country(),
					'email'      => 'payplug_applepay_email@payplug.com'
				], 'billing' );
				$order->set_address( [
					'first_name' => 'payplug_applepay_first_name',
					'last_name'  => 'payplug_applepay_last_name',
					'address_1'  => 'payplug_applepay_address',
					'address_2'  => '',
					'city'       => 'payplug_applepay_city',
					'postcode'   => 'payplug_applepay_psotcode',
					'country'    => WC()->countries->get_base_country(),
					'email'      => 'payplug_applepay_email@payplug.com'
				], 'shipping' );

				$order->set_payment_method($apple_pay);

				$packages = WC()->cart->get_shipping_packages();

				WC()->shipping()->reset_shipping();

				$order->calculate_taxes();

				$order->calculate_totals();

				$order->save();

				$cart->empty_cart();

				$this->process_cart_payment($order, $apple_pay);

			}catch (\Exception $exception){
				wp_send_json_error([
					'message' => __('Your order was cancelled.', 'woocommerce')
				]);
			}

		} else {
			wp_send_json_error();
		}
	}

	public function process_cart_payment($order ,$gateway) {
		$order_id = PayplugWoocommerceHelper::is_pre_30() ? $order->id : $order->get_id();
		$customer_id = PayplugWoocommerceHelper::is_pre_30() ? $order->customer_user : $order->get_customer_id();
		$amount      = (int) PayplugWoocommerceHelper::get_payplug_amount($order->get_total() - ($order->get_shipping_tax() + $order->get_shipping_total()));
		$amount      = $gateway->validate_order_amount($amount);
		wp_send_json([
			'total' => $amount,
			'order_id' => $order_id,
			'payment_data' => $gateway->process_standard_payment($order, $amount, $customer_id, 'product')
		]);

	}

	public function update_applepay_order() {
		$order_id = $_POST['order_id'];
		$order = wc_get_order( $order_id );

		$selected_shipping_method = !empty($_POST['shipping_method']) ? $_POST['shipping_method'] : null;
		if (!empty($_POST['shipping'])) {
			foreach ($_POST['shipping'] as $key => $data) {
				switch ($key) {
					case 'familyName':
						$order->set_shipping_last_name($data);
						break;
					case 'givenName':
						$order->set_shipping_first_name($data);
						break;
					case 'country':
						$order->set_shipping_country($data);
						break;
					case 'locality':
						$order->set_shipping_city($data);
						break;
					case 'phoneNumber':
						$order->set_shipping_phone($data);
						break;
					case 'postalCode':
						$order->set_shipping_postcode($data);
						break;
					case 'addressLines':
						$order->set_shipping_address_1($data[0]);
						if (!empty($data[1])) {
							$order->set_shipping_address_2($data[1]);
						}
						break;
					case 'emailAddress':
						$order->set_billing_email($data);
						break;
				}
			}
		}
		if (!empty($_POST['billing'])) {
			foreach ( $_POST['billing'] as $key => $data ) {
				switch ($key) {
					case 'familyName':
						$order->set_billing_last_name($data);
						break;
					case 'givenName':
						$order->set_billing_first_name($data);
						break;
					case 'addressLines':
						$order->set_billing_address_1($data[0]);
						if (!empty($data[1])) {
							$order->set_billing_address_2($data[1]);
						}
						break;
					case 'locality':
						$order->set_billing_city($data);
						break;
					case 'country':
						$order->set_billing_country($data);
						break;
					case 'postalCode':
						$order->set_billing_postcode($data);
						break;
				}
			}
		}

		$address_data = PayplugAddressData::from_order($order);

		$order->set_shipping_country($address_data->get_shipping()['country']);
		$order->set_billing_country($address_data->get_billing()['country']);

		$shipping_address= $address_data->get_shipping();
		$shipping_address['state'] = '';

		$package = array(
			'contents'        => array(),
			'contents_cost'   => 0,
			'destination'     => $shipping_address,
			'applied_coupons' => $order->get_used_coupons(),
			'user'            => array(
				'ID' => $order->get_customer_id()
			)
		);

		foreach ($order->get_items('shipping') as $item_id => $shipping_item) {
			$order->remove_item($item_id);
		}

		$shipping_zone = \WC_Shipping_Zones::get_zone_matching_package( $package );
		if ( $shipping_zone && !empty( $selected_shipping_method ) ) {

			$shipping_methods = $shipping_zone->get_shipping_methods( true );
			$use_taxes = false;

			foreach ( $shipping_methods as $shipping_method ) {
				if ( ! $shipping_method->supports( 'shipping-zones' ) || ! $shipping_method->is_enabled() ) {
					continue;
				}

				$id_shipping_method = $shipping_method->id.'_'.$shipping_method->instance_id;
				if ($id_shipping_method === $selected_shipping_method) {

					$shipping_method->calculate_shipping( $package );
					$rates = $shipping_method->get_rates_for_package($package);

					if ( ! empty( $rates ) ) {

						$rate = reset( $rates );

						$item = new \WC_Order_Item_Shipping();
						$item->set_method_title( $rate->get_label() );
						$item->set_method_id( $rate->get_id() );
						$item->set_total( $rate->get_cost() );

						if (!empty($rate->taxes)) {
							$use_taxes = true;
						}
						$shipping_taxes = \WC_Tax::calc_shipping_tax(
							$rate->get_cost(),
							$rate->get_taxes()
						);

						$item->set_taxes( [
							'total' => $shipping_taxes,
						] );

						$item->calculate_taxes();

						$item->save();

						$order->add_item( $item );
						break;
					}
				}
			}
		}

		$order->calculate_totals($use_taxes);
		$order->save();

		wp_send_json($order);

	}

	/**
	 * update the payment since customers can change their options during the payment
	 * @return void
	 * @throws \Payplug\Exception\ConfigurationNotSetException
	 */
	public function update_applepay_payment() {

		$applepay = new ApplePayGateway();

		$payment_id = $_POST['payment_id'];
		$order_id = $_POST['order_id'];
		$payment_token = $_POST['payment_token'];
		$amount = $_POST['amount'];

		$payment = \Payplug\Payment::retrieve($payment_id);

		$order = wc_get_order( $order_id );
		$amount      = (int) PayplugWoocommerceHelper::get_payplug_amount($amount);
		$amount      = $applepay->validate_order_amount($amount);

		$address_data = PayplugAddressData::from_order($order);

		// delivery_type must be removed in Apple Pay
		$billing = $address_data->get_billing();
		unset($billing['delivery_type']);
		$shipping = $address_data->get_shipping();
		unset($shipping['delivery_type']);

		$data = ['apple_pay' => array(
			"amount" => $amount,
			"payment_token" => $payment_token,
			"billing"          => $billing,
			"shipping"       => $shipping,
		)];

		$update = $payment->update($data);

		wp_send_json_success([
			'amount' => $amount,
			'update' => $update
		]);
	}

	public function applepay_cancel_order()
	{
		$payment_id = !empty($_POST['payment_id']) ? $_POST['payment_id'] : null;
		$order_id = $_POST['order_id'];

		if(empty($_POST['order_id'])){
			wp_send_json_error([
				'message' => __('Your order was cancelled.', 'woocommerce')
			]);
		}

		$order = wc_get_order($order_id);
		$items = $order->get_items();
		foreach ($items as $item) {
			$product_id = $item->get_product_id();
			$quantity = $item->get_quantity();
			$variation_id = $item->get_variation_id();
			$variations = array();

			if ($variation_id) {
				$product = wc_get_product($variation_id);
				$variations = $product->get_variation_attributes();
			}

			WC()->cart->add_to_cart($product_id, $quantity, $variation_id, $variations);
		}

		//if there's no payment created
		if (!empty($payment_id)){
			$options = PayplugWoocommerceHelper::get_payplug_options();
			$payplug_test_key = !empty($options['payplug_test_key']) ? $options['payplug_test_key'] : '';
			$payplug_live_key = !empty($options['payplug_live_key']) ? $options['payplug_live_key'] : '';

			if (empty($payplug_test_key) && empty($payplug_live_key)) {
				wp_send_json_error([
					'message' => __('Your order was cancelled.', 'woocommerce')
				]);
			}

			$payment = \Payplug\Payment::retrieve($payment_id, new Payplug($options['mode'] === 'yes' ? $payplug_live_key : $payplug_test_key));
			$payment->abort(new Payplug($options['mode'] === 'yes' ? $payplug_live_key : $payplug_test_key));
		}

		if ($order->delete(true)) {
			wp_send_json_success([
				'message' => __('Your order was cancelled.', 'woocommerce')
			]);
		} else {
			wp_send_json_error([
				'message' => __('Your order was cancelled.', 'woocommerce')
			]);
		}


	}

	public function applepay_empty_cart() {
		try {
			WC()->cart->empty_cart();
			wp_send_json_success();
		} catch (\Exception $e) {
			wp_send_json_error([
				'message' => __('Your order was cancelled.', 'woocommerce')
			]);
		}
	}

	public function applepay_add_to_cart() {
		try {
			if (!empty($_POST['product_id'])) {
				$product_id = $_POST['product_id'];
			} else {
				$product_id = $_POST['product_variation_id'];
			}

			$product_quantity = !empty($_POST['product_quantity']) ? $_POST['product_quantity'] : 1;

			WC()->cart->add_to_cart($product_id, $product_quantity);
			wp_send_json_success([
				'total' => WC()->cart->total - WC()->cart->shipping_total
			]);
		} catch (\Exception $e) {
			wp_send_json_error([
				'message' => __('Your order was cancelled.', 'woocommerce')
			]);
		}
	}

}
