<?php

namespace Ilabs\Inpost_International\Settings;

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

use Ilabs\Inpost_International\Helpers\Helper;

/**
 * Product_Settings
 */
class Product_Settings {

	/**
	 * META_ALLOWED_SHIPPING_METHODS
	 */
	const META_ALLOWED_SHIPPING_METHODS = 'inpost_international_shipping_methods_allowed';

	/**
	 * META_PARCEL_TEMPLATE
	 */
	const META_PARCEL_TEMPLATE = 'inpost_international_parcel_template';

	/**
	 * Inpost methods
	 *
	 * @var $inpost_methods $inpost_methods.
	 */
	public static $inpost_methods;

	/**
	 * Helper instance for utility functions.
	 *
	 * @since 1.0.0
	 * @var Helper An instance of the Helper class that provides utility methods.
	 */
	private $helper;

	/**
	 * Constructor
	 */
	public function __construct() {
		$this->helper = Helper::init();
		$this->hooks();
	}

	/**
	 * Product edit hooks
	 *
	 * @return void
	 */
	public function hooks() {
		add_filter( 'woocommerce_product_data_tabs', array( $this, 'product_data_tabs' ), 10, 1 );
		add_action( 'woocommerce_product_data_panels', array( $this, 'product_data_panels' ), 10, 0 );
		add_action( 'woocommerce_admin_process_product_object', array( $this, 'save_product_settings' ), 10, 1 );
		add_action( 'woocommerce_product_options_shipping', array( $this, 'choose_product_template' ), 10, 0 );
	}


	/**
	 * Get product config by product ID
	 *
	 * @param int $product_id $product_id.
	 *
	 * @return array|null
	 */
	public function get_config_by_product_id( $product_id ) {
		$meta = get_post_meta( $product_id, self::META_ALLOWED_SHIPPING_METHODS, true );
		// if saved zero methods (all methods unchecked before save) - we have empty array.
		// if product is new - return null to show all checked in is_checked function.
		return is_array( $meta ) ? $meta : null;
	}

	/**
	 * Get inpost methods by product_id
	 *
	 * @param int $product_id $product_id.
	 *
	 * @return array
	 */
	private function get_inpost_methods_by_product_id( $product_id ) {
		$return = array();

		$product_config = $this->get_config_by_product_id( $product_id );

		if ( is_array( $product_config ) ) {
			return $product_config;
		}

		$all_inpost_methods = $this->helper->get_inpost_shipping_methods();
		// default all allowed.
		if ( ! empty( $all_inpost_methods ) ) {
			foreach ( $all_inpost_methods as $method ) {
				$return[] = $method['method_title_with_id'];
			}
		}

		return $return;
	}


	/**
	 * Add custom product setting tab.
	 *
	 * @param  array $default_tabs $default_tabs.
	 */
	public function product_data_tabs( $default_tabs ) {
		$default_tabs['inpost_intl_product_tab'] = array(
			'label'    => esc_html__( 'InPost International', 'inpost-international' ),
			'target'   => 'inpost_intl_custom_tab_data',
			'priority' => 61,
			'class'    => array(),
		);

		return $default_tabs;
	}

	/**
	 * Is checkbox checked
	 *
	 * @param array|null $config_by_product $config_by_product.
	 * @param string     $method_id  $method_id.
	 *
	 * @return bool
	 */
	private function is_checked( $config_by_product, $method_id ) {

		// first time product open for edit.
		if ( ! $config_by_product ) {
			return true;
		}

		if ( is_array( $config_by_product ) && in_array( $method_id, $config_by_product, true ) ) {
			return true;
		}

		return false;
	}

	/**
	 * Contents custom product setting tab.
	 */
	public function product_data_panels() {
		global $post;
		echo '<div id="inpost_intl_custom_tab_data" class="panel woocommerce_options_panel inpost_intl_panel">';

		$product_config = $this->get_config_by_product_id( $post->ID );
		$inpost_methods = $this->helper->get_inpost_shipping_methods();

		if ( is_array( $inpost_methods ) ) {
			foreach ( $inpost_methods as $key => $method ) {
				woocommerce_wp_checkbox(
					array(
						'id'    => $this->get_post_key_from_method_instance_id( $key ),
						'label' => $method['user_title'],
						'value' => $this->is_checked( $product_config, $method['method_title_with_id'] ) ? 'yes' : null,
					)
				);
			}
		}

		echo '</div>';
	}

	/**
	 * Get_post_key_from_method_id
	 *
	 * @param mixed $instance_id $instance_id.
	 *
	 * @return string
	 */
	private function get_post_key_from_method_instance_id( $instance_id ) {
		return '_inpost_international_shipping_method_id_' . $instance_id;
	}


	/**
	 * Save the checkbox.
	 *
	 * @param \WC_Product $product $product.
	 */
	public function save_product_settings( $product ) {
		$allowed_methods = array();
		$inpost_methods  = $this->helper->get_inpost_shipping_methods();
		if ( is_array( $inpost_methods ) ) {
			foreach ( $inpost_methods as $key => $method ) {
				$post_key = $this->get_post_key_from_method_instance_id( $key );
				if ( isset( $_POST[ $post_key ] ) && 'yes' === $_POST[ $post_key ] ) {
					$allowed_methods[] = $method['method_title_with_id'];
				}
			}
		}

		$product->update_meta_data( self::META_ALLOWED_SHIPPING_METHODS, $allowed_methods );

		if ( isset( $_POST['inpost_intl_parcel_dimensions'] ) && ! empty( $_POST['inpost_intl_parcel_dimensions'] ) ) {
			$product->update_meta_data( self::META_PARCEL_TEMPLATE, sanitize_text_field( wp_unslash( $_POST['inpost_intl_parcel_dimensions'] ) ) );
		}

		// clear shipping methods cache.
		\WC_Cache_Helper::get_transient_version( 'shipping', true );
	}

	/**
	 * Return allowed InPost shipping methods defined for products in cart
	 *
	 * @param array $contents_of_the_cart $contents_of_the_cart.
	 *
	 * @return array
	 */
	public function get_methods_allowed_by_cart( $contents_of_the_cart ) {

		$allowed_for_product = array();
		$physical_goods_ids  = array();
		$total_weight        = 0;

		foreach ( $contents_of_the_cart as $cart_item_key => $cart_item ) {

			// if variation in cart.
			if ( $cart_item['variation_id'] ) {

				$variant = wc_get_product( $cart_item['variation_id'] );
				if ( ! $variant->is_virtual() ) {
					$physical_goods_ids[] = $cart_item['product_id'];
					$total_weight        += floatval( $variant->get_weight() ) * $cart_item['quantity'];
				}
			} else {

				$_product = wc_get_product( $cart_item['product_id'] );
				if ( ! $_product->is_virtual() ) {
					$physical_goods_ids[] = $cart_item['product_id'];
					$total_weight        += floatval( $_product->get_weight() ) * $cart_item['quantity'];
				}
			}
		}

		$physical_goods_ids = array_unique( $physical_goods_ids );

		if ( ! empty( $physical_goods_ids ) ) {

			$product_section_settings = get_option( 'inpost_international_settings_products' );
			// Allow all shipping methods for all products.
			if ( ! empty( $product_section_settings['allow_all'] ) ) {

				$inpost_methods = $this->helper->get_inpost_shipping_methods();
				if ( is_array( $inpost_methods ) ) {
					foreach ( $inpost_methods as $method ) {
						$allowed_for_product[] = $method['method_title_with_id'];
					}
				}

				return $this->block_overweight( $total_weight, $allowed_for_product );

			} else {

				foreach ( $physical_goods_ids as $id ) {
					$allowed_for_product[ $id ] = $this->get_inpost_methods_by_product_id( $id );
				}

				if ( count( $physical_goods_ids ) === 1 ) {
					return $this->block_overweight( $total_weight, $allowed_for_product[ $id ] );
				}

				if ( is_array( $allowed_for_product ) && count( $allowed_for_product ) > 1 ) {
					$allowed_for_product = call_user_func_array( 'array_intersect', $allowed_for_product );
					$allowed_for_product = $this->block_overweight( $total_weight, $allowed_for_product );
				}
			}
		}

		return $allowed_for_product;
	}


	/**
	 * Add option with parcel dimensions on product edit page
	 */
	public function choose_product_template() {
		global $post;

		$options = $this->helper->get_template_options();

		woocommerce_wp_select(
			array(
				'id'                => 'inpost_intl_parcel_dimensions',
				'label'             => esc_html__( 'InPost International template', 'inpost-international' ),
				'options'           => $options,
				'value'             => get_post_meta( $post->ID, self::META_PARCEL_TEMPLATE, true ),
				'custom_attributes' => array(),
			)
		);
	}


	/**
	 * Block weight over 25 kg shipments
	 *
	 * @param float $total_weight $total_weight.
	 * @param array $product_config $product_config.
	 */
	private function block_overweight( $total_weight, $product_config ) {

		$sending_options = get_option( 'inpost_international_settings_sending' );

		if ( ! empty( $sending_options['block_over_weight'] ) ) {

			if ( $total_weight >= 25 ) {

				if ( ! empty( $product_config ) && is_array( $product_config ) ) {

					foreach ( $product_config as $key => $allowed_method ) {
						if ( 0 === strpos( $allowed_method, 'inpost_international_' ) ) {
							unset( $product_config[ $key ] );

							// integration with Flexible Shipping.
						} elseif ( 0 === strpos( $allowed_method, 'flexible_shipping' ) ) {
							$instance_id = '';
							if ( stripos( $allowed_method, ':' ) ) {
								$instance_id = trim( explode( ':', $allowed_method )[1] );
							}
							if ( ! empty( $instance_id ) ) {
								$linked_method = $this->helper->get_method_linked_to_fs_by_instance_id( $instance_id );

								if ( 0 === strpos( $linked_method, 'inpost_international_' ) ) {
									unset( $product_config[ $key ] );
								}
							}
						}
					}
				}
			}
		}

		return $product_config;
	}
}
