<?php

namespace Svea_Webpay_For_Woocommerce;

use Svea_Webpay_For_Woocommerce\Gateways\WC_Gateway_Abstract;
use Svea_Webpay_For_Woocommerce\Gateways\WC_Gateway_Svea_Card;
use Svea_Webpay_For_Woocommerce\Gateways\WC_Gateway_Svea_Invoice;
use Svea_Webpay_For_Woocommerce\Gateways\WC_Gateway_Svea_Part_Pay;
use WC_Order;

if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

/**
 * Class to handle function related to orders
 */
class Order_Functions {

	/**
	 * Initialize the class
	 *
	 * @return void
	 */
	public function init() {

		add_filter( 'woocommerce_subscriptions_update_payment_via_pay_shortcode', [ $this, 'should_update_payment_method' ], 10, 3 );

		add_action( 'woocommerce_order_status_completed', [ $this, 'sync_delivered_order' ], 10, 1 );
		add_action( 'woocommerce_order_status_cancelled', [ $this, 'sync_cancelled_order' ], 10, 1 );
		add_action( 'woocommerce_order_status_refunded', [ $this, 'sync_refunded_order' ], 10, 1 );

		add_action( 'woocommerce_cart_calculate_fees', [ $this, 'add_invoice_fee' ], 40 );

		add_action( 'woocommerce_after_checkout_validation', [ $this, 'checkout_validation_handler' ], 10, 2 );

		if ( ! is_admin() ) {
			add_filter( 'pre_option_woocommerce_ship_to_destination', [ $this, 'maybe_force_ship_to_billing_address' ], 10, 2 );
		}

		add_filter( 'woocommerce_get_order_item_totals', [ $this, 'receipt_display_svea_order_id' ], 10, 2 );

		add_action( 'wc_ajax_update_order_review', [ $this, 'save_customer_type' ], 5 );
		add_action( 'wc_ajax_nopriv_update_order_review', [ $this, 'save_customer_type' ], 5 );
	}

	/**
	 * Save the customer type
	 *
	 * @return void
	 */
	public function save_customer_type() {
		$payment_method = isset( $_POST['payment_method'] ) ? sanitize_text_field( $_POST['payment_method'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
		parse_str( sanitize_text_field( wp_unslash( $_POST['post_data'] ) ), $post_data ); // phpcs:ignore WordPress.Security.NonceVerification.Missing

		$customer_type = 'individual';

		if ( isset( $post_data[ 'iv_billing_customer_type_' . $payment_method ] ) ) {
			$customer_type = sanitize_text_field( $post_data[ 'iv_billing_customer_type_' . $payment_method ] );
		}

		if ( isset( $post_data[ 'pp_billing_customer_type_' . $payment_method ] ) ) {
			$customer_type = sanitize_text_field( $post_data[ 'pp_billing_customer_type_' . $payment_method ] );
		}

		if ( $customer_type === 'false' ) {
			$customer_type = 'individual';
		}

		WC()->session->set( 'svea_customer_type', $customer_type );

	}

	/**
	 * Parent function that calls checkout validation handlers depending
	 * on payment gateway
	 *
	 * @return  void
	 */
	public function checkout_validation_handler( $fields, $errors ) {
		if ( ! isset( $fields['payment_method'] ) ) {
			return;
		}

		$payment_method_id = $fields['payment_method'];

		$wc_gateway = WC_Gateway_Abstract::get_gateway_instance( $payment_method_id );

		/**
		 * Use the validation handlers in the gateway-classes depending
		 * on the chosen payment method
		 */
		if ( is_object( $wc_gateway ) && method_exists( $wc_gateway, 'checkout_validation_handler' ) ) {
			$wc_gateway->checkout_validation_handler( $fields, $errors );
		}
	}

	/**
	 * Maybe force the ship to billing address
	 *
	 * @param mixed $value
	 * @return mixed
	 */
	public function maybe_force_ship_to_billing_address( $value ) {
		// Get current gateway
		$current_gateway = Helper::get_current_gateway();

		if ( $current_gateway && method_exists( $current_gateway, 'can_ship_to_different_address' )
			&& ! $current_gateway->can_ship_to_different_address() ) {
			// If the gateway does not allow shipping to a different address, force the value to 'billing_only'
			$value = 'billing_only';
		}

		return $value;
	}

	/**
	 * Display the svea order id whilst viewing the receipt
	 *
	 * @param   array       $total_rows     the table rows in receipt view
	 * @param   WC_Order    $wc_order          the order currently being viewed
	 * @return  array       an array of the order rows
	 */
	public function receipt_display_svea_order_id( $total_rows, $wc_order ) {
		$svea_order_id = $wc_order->get_meta( '_svea_order_id' );

		if ( ! $svea_order_id )
		return $total_rows;

		$total_rows['transaction_id'] = [
			'value' => '#' . $svea_order_id,
			'label' => esc_html__( 'Svea transaction id: ', 'svea-webpay-for-woocommerce' ),
		];

		$order_total = $total_rows['order_total'];
		unset( $total_rows['order_total'] );
		$total_rows['order_total'] = $order_total;
		return $total_rows;
	}

	/**
	 * Adds an invoice fee to the WooCommerce cart if
	 * it has been set in the invoice gateway
	 *
	 * @return void
	 */
	public function add_invoice_fee() {
		$current_gateway = Helper::get_current_gateway();

		if ( ! $current_gateway || get_class( $current_gateway ) !== 'Svea_Webpay_For_Woocommerce\Gateways\WC_Gateway_Svea_Invoice' ) {
			return;
		}

		WC_Gateway_Svea_Invoice::init()->add_invoice_fee();
	}

	/**
	 * Disable Subscriptions default way of changing payment method
	 * in favor to implement our own way
	 *
	 * @param   boolean             $update     whether or not the payment method should be updated
	 * @param   string              $new_payment_method     the payment method that the subscription is changed to
	 * @param   WC_Subscription     $subscription   the subscription object
	 * @return  boolean     whether or not the payment method should be updated
	 */
	public function should_update_payment_method( $update, $new_payment_method, $subscription ) {
		if (
			$new_payment_method === WC_Gateway_Svea_Invoice::GATEWAY_ID ||
			$new_payment_method === WC_Gateway_Svea_Card::GATEWAY_ID
		) {
			$update = false;
		}

		return $update;
	}

	/**
	 * Sync refunded orders to Svea
	 *
	 * @param   int     $order_id   id of the order being refunded
	 *
	 * @return  void
	 */
	public function sync_refunded_order( $order_id ) {
		$wc_order = new WC_Order( $order_id );

		$svea_order_id = $wc_order->get_meta( '_svea_order_id' );

		if ( ! $svea_order_id || strlen( $svea_order_id ) <= 0 ) {
			return;
		}

		$payment_method_id = $wc_order->get_payment_method();

		$wc_gateway = WC_Gateway_Abstract::get_gateway_instance( $payment_method_id );

		if ( $wc_gateway !== false && $wc_gateway->get_option( 'disable_order_sync' ) !== 'yes' ) {
			$wc_gateway->credit_order( $wc_order, $svea_order_id );
		}
	}

	/**
	 * Sync cancelled orders to Svea
	 *
	 * @param   int     $order_id   id of the order being cancelled
	 *
	 * @return  void
	 */
	public function sync_cancelled_order( $order_id ) {
		$wc_order = wc_get_order( $order_id );

		$svea_order_id = $wc_order->get_meta( '_svea_order_id' );

		/**
		 * Determine if this order is a Svea order
		 */
		if ( ! $svea_order_id || strlen( $svea_order_id ) <= 0 ) {
			return;
		}

		$payment_method_id = $wc_order->get_payment_method();

		$wc_gateway = WC_Gateway_Abstract::get_gateway_instance( $payment_method_id );

		/**
		 * If current gateway is a Svea gateway and order sync is enabled
		 * sync the order to Svea
		 */
		if ( $wc_gateway !== false && $wc_gateway->get_option( 'disable_order_sync' ) !== 'yes' ) {
			$wc_gateway->cancel_order( $wc_order, $svea_order_id );
		}
	}

	/**
	 * Sync delivered orders to Svea
	 *
	 * @param   int     $order_id   id of the order being delivered
	 * @return  void
	 */
	public function sync_delivered_order( $order_id ) {
		$wc_order = wc_get_order( $order_id );

		$svea_order_id = $wc_order->get_meta( '_svea_order_id' );

		if ( ! $svea_order_id || strlen( $svea_order_id ) <= 0 ) {
			return;
		}

		$payment_method_id = $wc_order->get_payment_method();

		$wc_gateway = WC_Gateway_Abstract::get_gateway_instance( $payment_method_id );

		if ( $wc_gateway !== false && $wc_gateway->get_option( 'disable_order_sync' ) !== 'yes' ) {
			$wc_gateway->deliver_order( $wc_order, $svea_order_id );
		}
	}
}
