<?php

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


/**
 * TODO: This implementation is temporary and will probably be changed during implementation of currently pending cart task
 *
 * Class Wiaas_Cart
 */
class Wiaas_Cart {


	public static function init() {
		add_action( 'woocommerce_checkout_create_order_line_item', array( __CLASS__, 'add_order_item_meta' ), 10, 3 );

		add_filter( 'woocommerce_hidden_order_itemmeta', array( __CLASS__, 'hidden_order_item_meta' ) );

		add_filter( 'woocommerce_add_cart_item_data', array( __CLASS__, 'add_cart_item_data' ), 10, 2 );

		add_action( 'woocommerce_before_calculate_totals', array( __CLASS__, 'on_calculate_totals' ), 99, 1);

		add_action( 'woocommerce_cart_loaded_from_session', array( __CLASS__, 'on_calculate_totals' ), 99, 1);

		// Add options and addons to cart.
		add_action( 'woocommerce_add_to_cart', array( __CLASS__, 'add_additional_packages_to_cart' ), 10, 6 );
	}


	/**
	 * Extend cart item data with wiaas package payment info and addons and options
	 *
	 * Every package cart item will be extended with its payment info but only standard package type
	 * will be extended with addons and options arrays
	 *
	 * @param $cart_item_data
	 * @param $package_id
	 *
	 * @return array
	 */
	public static function add_cart_item_data($cart_item_data, $package_id) {

		$is_valid = isset( $_POST[ 'price_id' ]) &&
		            WC_Product_Factory::get_product_type( $package_id ) === 'bundle';

		if (!$is_valid) {
			return $cart_item_data;
		}

		$package_type = Wiaas_Package_Type::get_package_type($package_id);

		$package = wc_get_product( $package_id );

		switch ($package_type) {
			case 'standard':

				$cart_item['_wiaas_standard_package'] = true;

				// Prepare addons additional data for later use.
				if ( ! isset( $cart_item_data['_wiaas_addon_items'] ) ) {
					$cart_item_data['_wiaas_addon_items' ] = array();
				}
				// Prepare options additional data for later use.
				if ( ! isset( $cart_item_data['_wiaas_option_items'] ) ) {
					$cart_item_data['_wiaas_option_items' ] = array();
				}

				$country = Wiaas_Countries::get_package_country($package);
				if (isset($country)) {
					$cart_item_data['_wiaas_currency'] = $country['currency'];
				}

				$package_prices = Wiaas_Pricing::get_standard_package_customer_prices($package);
				break;
			case 'add_on':
				$parent_key = $cart_item_data['_wiaas_addon_for'];
				$parent_item = WC()->cart->get_cart_item($parent_key);

				$package_prices = Wiaas_Pricing::get_addon_package_customer_price($package, $parent_item['data']);
				break;
			case 'option':
				$parent_key = $cart_item_data['_wiaas_option_for'];
				$parent_item = WC()->cart->get_cart_item($parent_key);

				$option_group_name = Wiaas_Package_Option_Groups::get_group_name_for_package_option($parent_item['data'], $package);
				$cart_item_data['_wiaas_option_group_name' ] = $option_group_name;

				$package_prices =  Wiaas_Pricing::get_option_package_customer_price($package, $parent_item['data']);
				break;
		}

		$selected_price_index = array_search($_POST['price_id'], array_column($package_prices, 'id'));

		if (is_numeric($selected_price_index) && isset($package_prices[$selected_price_index])) {
			$cart_item_data['_wiaas_payment'] = $package_prices[$selected_price_index];
		}

		return $cart_item_data;
	}

	/**
	 * Add selected package options and addons after parent standard package is added to cart
	 *
	 * @param $cart_item_key
	 * @param $package_id
	 * @param $quantity
	 * @param $variation_id
	 * @param $variation
	 * @param $cart_item_data
	 */
	public static function add_additional_packages_to_cart($cart_item_key, $package_id, $quantity, $variation_id, $variation, $cart_item_data) {

		remove_action( 'woocommerce_add_to_cart', array( __CLASS__, 'add_additional_packages_to_cart' ));

		self::_add_options_to_cart($cart_item_key, $package_id, $cart_item_data);

		self::_add_addons_to_cart($cart_item_key, $package_id, $cart_item_data);

		add_action( 'woocommerce_add_to_cart', array( __CLASS__, 'add_additional_packages_to_cart' ), 10, 6 );
	}

	/**
	 * Update package cart item with `minimal_fixed_price` as its price
	 * so resulting totals would be sum of these prices
	 * @param $cart
	 */
	public static function on_calculate_totals($cart) {

		foreach ($cart->cart_contents as $key => $cart_item) {
			if (isset($cart_item['_wiaas_standard_package']))  {

				$total = self::get_cart_item_total($cart_item);

				WC()->cart->cart_contents[ $key ]['data']->set_price( $total['fixed_extra'] );

			} else {
				WC()->cart->cart_contents[ $key ]['data']->set_price( 0 );
			}
		}
	}

	/**
	 * Persist used payment type information for package in corresponding order line item.
	 * Also for standard package type list of addons and options will be saved.
	 *
	 * @param $order_item
	 * @param $cart_item_key
	 * @param $cart_item
	 * @param $order
	 *
	 * @return array
	 */
	public static function add_order_item_meta( $order_item, $cart_item_key, $cart_item ) {
		if (wc_pb_is_bundle_container_cart_item($cart_item) && isset($cart_item['_wiaas_payment'])) {

			$payment = $cart_item['_wiaas_payment'];

			$total = self::get_cart_item_total($cart_item);

			$order_item->add_meta_data( '_wiaas_payment_type', $payment['payment_type'], true );
			$order_item->add_meta_data( '_wiaas_services_extra', $total['services_extra'], true );
			$order_item->add_meta_data( '_wiaas_service_contract_period', $payment['services_contract_period'], true );
			$order_item->add_meta_data( '_wiaas_max_contract_period', $payment['max_contract_period'], true );
			$order_item->add_meta_data( '_wiaas_period_unit', $payment['period_unit'], true );
			$order_item->add_meta_data( '_wiaas_recurrent_extra', $total['recurrent_extra'], true );
			$order_item->add_meta_data( '_wiaas_pay_period', $payment['package_pay_period'], true );
		}

		if (isset($cart_item['_wiaas_standard_package'])) {
			$order_item->add_meta_data( '_wiaas_standard_package', $cart_item['_wiaas_standard_package'], true );
		}
		if (isset($cart_item['_wiaas_currency'])) {
			$order_item->add_meta_data( '_wiaas_currency', $cart_item['_wiaas_currency'], true );
		}

		// add options metadata
		if (isset($cart_item['_wiaas_option_items'])) {
			$order_item->add_meta_data( '_wiaas_option_items', $cart_item['_wiaas_option_items'] );
		}
		if (isset($cart_item['_wiaas_option_for'])) {
			$order_item->add_meta_data( '_wiaas_option_for', $cart_item['_wiaas_option_for'], true );
		}
		if (isset($cart_item['_wiaas_option_group_name'])) {
			$order_item->add_meta_data( '_wiaas_option_group_name', $cart_item['_wiaas_option_group_name'], true );
		}

		// add addons metadata
		if (isset($cart_item['_wiaas_addon_items'])) {
			$order_item->add_meta_data( '_wiaas_addon_items', $cart_item['_wiaas_addon_items'] );
		}
		if (isset($cart_item['_wiaas_addon_for'])) {
			$order_item->add_meta_data( '_wiaas_addon_for', $cart_item['_wiaas_addon_for'], true );
		}
	}

	/**
	 * Mark extended properties for order as hidden
	 * @param $hidden
	 *
	 * @return array
	 */
	public static function hidden_order_item_meta( $hidden ) {

		return array_merge( $hidden, array(
			'_wiaas_payment_type',
			'_wiaas_services_extra',
			'_wiaas_service_contract_period',
			'_wiaas_max_contract_period',
			'_wiaas_period_unit',
			'_wiaas_recurrent_extra',
			'_wiaas_pay_period',
			'_wiaas_addon_items',
			'_wiaas_addon_for',
			'_wiaas_option_items',
			'_wiaas_option_for',
			'_wiaas_option_group_name',
			'_wiaas_standard_package',
			'_wiaas_currency',
		) );
	}

	/**
	 * Calculate total cost for cart item
	 *
	 * @param $cart_item
	 *
	 * @return array
	 */

	public static function get_cart_item_total($cart_item) {

		$package_price = isset($cart_item['_wiaas_payment']) ? $cart_item['_wiaas_payment'] : array(
			'fixed_extra' => 0,
			'services_extra' => 0,
			'recurrent_extra' => 0
		);

		$total_fixed_extra = $package_price['fixed_extra'];
		$total_services_extra = $package_price['services_extra'];
		$total_recurrent_extra = $package_price['recurrent_extra'];

		$cart_item_addons = wiaas_get_cart_item_addons($cart_item);
		foreach ($cart_item_addons as $cart_item_addon) {
			$addon_price = $cart_item_addon['_wiaas_payment'];
			$total_fixed_extra += $addon_price['fixed_extra'];
			$total_services_extra += $addon_price['services_extra'];
			$total_recurrent_extra += $addon_price['recurrent_extra'];
		}

		$cart_item_options = wiaas_get_cart_item_options($cart_item);
		foreach ($cart_item_options as $cart_item_option) {
			$option_price = $cart_item_option['_wiaas_payment'];
			$total_fixed_extra += $option_price['fixed_extra'];
			$total_services_extra += $option_price['services_extra'];
			$total_recurrent_extra += $option_price['recurrent_extra'];
		}

		return array(
			'fixed_extra' => $total_fixed_extra,
			'services_extra' => $total_services_extra,
			'recurrent_extra' => $total_recurrent_extra
		);
	}


	//PRIVATE

	/**
	 * Add selected package options to cart
	 * @param $cart_item_key
	 * @param $package_id
	 * @param $cart_item_data
	 *
	 * @throws Exception
	 */
	private static function _add_options_to_cart($cart_item_key, $package_id, $cart_item_data) {
		$is_option_parent = $_POST['package_id'] = $package_id && isset($cart_item_data['_wiaas_option_items']);
		$has_selected_options = isset($_POST['options']) && is_array($_POST['options']);

		if ($is_option_parent && $has_selected_options) {

			$options_ids = $_POST['options'];

			foreach ($options_ids as $option_id) {
				$option_package = wc_get_product($option_id);
				if (is_object($option_package)) {

					$option_cart_item_key = WC()->cart->add_to_cart($option_id, 1, 0, array(), array(
						'_wiaas_option_for' => $cart_item_key
					));

					if ($option_cart_item_key) {
						WC()->cart->cart_contents[ $cart_item_key ]['_wiaas_option_items'][] = $option_cart_item_key;
					}
				}
			}
		}
	}

	/**
	 * Add selected package addons to cart
	 *
	 * @param $cart_item_key
	 * @param $package_id
	 * @param $cart_item_data
	 *
	 * @throws Exception
	 */
	private static function _add_addons_to_cart($cart_item_key, $package_id, $cart_item_data) {

		$is_addon_parent = $_POST['package_id'] = $package_id && isset($cart_item_data['_wiaas_addon_items']);
		$has_selected_addons = isset($_POST['addons']) && is_array($_POST['addons']);

		if ($is_addon_parent && $has_selected_addons) {
			$addons_ids = $_POST['addons'];

			foreach ($addons_ids as $addon_id) {
				$addon_package = wc_get_product($addon_id);
				if (is_object($addon_package)) {

					$addon_cart_item_key = WC()->cart->add_to_cart($addon_id, 1, 0, array(), array(
						'_wiaas_addon_for' => $cart_item_key
					));

					if ($addon_cart_item_key) {
						WC()->cart->cart_contents[ $cart_item_key ]['_wiaas_addon_items'][] = $addon_cart_item_key;
					}
				}
			}
		}
	}
}

Wiaas_Cart::init();