<?php
/**
 * Inpost international Shipping method
 */

namespace Ilabs\Inpost_International\Shipping;

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

use Ilabs\Inpost_International\Helpers\Helper;
use WC_Eval_Math;
use WC_Shipping_Method;

/**
 * Shipping_Method
 */
class Shipping_Method_Base extends WC_Shipping_Method {


	/**
	 * Cost of order on which Free shipping will be applied.
	 *
	 * @var string Free shipping cost.
	 */
	protected string $free_shipping_cost;

	/**
	 * Shipping method type.
	 *
	 * @var string
	 */
	protected string $type;

	/**
	 * Is fixed cost per order enabled.
	 *
	 * @var string Is flat cost per order.
	 */
	protected string $flat_rate;

	/**
	 * Cost passed to [fee] shortcode.
	 *
	 * @var string Cost.
	 */
	protected string $fee_cost = '';

	/**
	 * Fixed cost per order.
	 *
	 * @var string Cost per order.
	 */
	protected string $cost_per_order;

	/**
	 * Cost based on rule.
	 *
	 * @var string Based on.
	 */
	protected string $based_on;

	/**
	 * Show or not free shipping label.
	 *
	 * @var string Show free shipping label yes/no
	 */
	protected string $show_free_shipping_label;

	/**
	 * Ignore discounts.
	 *
	 * If set, free shipping would be available based on pre-discount order amount.
	 *
	 * @var string
	 */
	public string $ignore_discounts;


	/**
	 * Shipping_Method constructor.
	 *
	 * @param int $instance_id Shipping method instance.
	 */
	public function __construct( $instance_id = 0 ) {
		parent::__construct( $instance_id );

		$this->instance_id = absint( $instance_id );
		$this->supports    = array(
			'shipping-zones',
			'instance-settings',
		);

		$this->id                 = 'inpost_international_automated_locker_point';
		$this->method_description = esc_html__(
			'Allow customers to pick up orders themselves in APM, PUDO or HUB.',
			'inpost-international'
		);

		$this->method_title = esc_html__( 'InPost International', 'inpost-international' );
		$this->init();
	}


	/**
	 * Init Shipping Method settings
	 *
	 * @return void
	 */
	public function init(): void {
		$this->init_form_fields();
		$this->init_settings();
		$this->title                    = $this->get_option( 'title' );
		$this->free_shipping_cost       = $this->get_option( 'free_shipping_cost' );
		$this->show_free_shipping_label = $this->get_option( 'show_free_shipping_label' );
		$this->type                     = $this->get_option( 'type', 'class' );
		$this->flat_rate                = $this->get_option( 'flat_rate' );
		$this->cost_per_order           = $this->get_option( 'cost_per_order' );
		$this->based_on                 = $this->get_option( 'based_on' );
		$this->tax_status               = $this->get_option( 'tax_status' );
		$this->ignore_discounts         = $this->get_option( 'apply_minimum_order_rule_before_coupon' );

		$this->setup_hooks();
	}


	/**
	 * Init additional hooks
	 *
	 * @return void
	 */
	private function setup_hooks(): void {
		add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
	}


	/**
	 * Admin options
	 *
	 * @return void
	 */
	public function admin_options(): void {
		?>
		<table class="form-table">
			<?php $this->generate_settings_html(); ?>
		</table>
		<?php
	}

	/**
	 * Generate HTML with table rates based on
	 *
	 * @return mixed
	 * @throws \Exception Exception.
	 */
	public function generate_rates_html() {

		$helper = Helper::init();

		$rates          = $helper->get_rates_saved_for_shipping_method( $this->id, $this->instance_id );
		$template_rates = $helper->get_template_rates_saved_for_shipping_method( $this->id, $this->instance_id );

		ob_start();

		inpost_intl_core()->locate_template(
			'shipping-method-rates-table.php',
			array(
				'rates'          => $rates,
				'template_rates' => $template_rates,
			)
		);

		return ob_get_clean();
	}


	/**
	 * Init form fields
	 *
	 * @return void
	 */
	public function init_form_fields(): void {

		$settings = array(
			array(
				'title'       => esc_html__( 'General settings', 'inpost-international' ),
				'type'        => 'title',
				'description' => '',
				'id'          => 'section_general_settings',
			),
			'logo_selected'                          => array(
				'name'  => '',
				'title' => esc_html__( 'Choose logo', 'inpost-international' ),
				'type'  => 'logo_selected',
				'id'    => 'logo_selected',
			),
			'logo_custom'                            => array(
				'name'              => '',
				'title'             => '',
				'type'              => 'text',
				'id'                => 'logo_custom',
				'custom_attributes' => array(
					'hidden' => true,
				),
			),
			'title'                                  => array(
				'title'    => esc_html__( 'Method title', 'inpost-international' ),
				'type'     => 'text',
				'default'  => esc_html__( 'InPost International', 'inpost-international' ),
				'desc_tip' => false,
			),
            'delivery_terms'                                  => array(
                'title'    => esc_html__( 'Terms of delivery', 'inpost-international' ),
                'type'     => 'text',
                'default'  => '',
                'desc_tip' => false,
            ),
			'insurance_inpost_intl'                  => array(
				'title'       => esc_html__( 'Insurance', 'inpost-international' ),
				'label'       => esc_html__( 'Set from order amount', 'inpost-international' ),
				'type'        => 'checkbox',
				'description' => '',
				'default'     => 'no',
				'desc_tip'    => true,
			),
			'insurance_value_inpost_intl'            => array(
				'title'             => esc_html__( 'Default insurance amount', 'inpost-international' ),
				'type'              => 'number',
				'custom_attributes' => array(
					'step' => 'any',
					'min'  => '0',
				),
				'default'           => '',
				'desc_tip'          => false,
				'placeholder'       => '0.00',
			),
			'free_shipping_cost'                     => array(
				'title'             => esc_html__( 'Free shipping', 'inpost-international' ),
				'type'              => 'number',
				'custom_attributes' => array(
					'step' => 'any',
					'min'  => '0',
				),
				'default'           => '',
				'desc_tip'          => esc_html__(
					'Enter the amount of the order from which the shipping will be free (does not include virtual products). ',
					'inpost-international'
				),
				'placeholder'       => '0.00',
			),
			'show_free_shipping_label'               => array(
				'title'       => '',
				'label'       => esc_html__( 'Add label "(free)" to the end of title of shipping method', 'inpost-international' ),
				'type'        => 'checkbox',
				'description' => '',
				'default'     => 'yes',
				'desc_tip'    => true,
			),
			'apply_minimum_order_rule_before_coupon' => array(
				'title'       => esc_html__( 'Coupons discounts', 'inpost-international' ),
				'label'       => esc_html__( 'Apply minimum order rule before coupon discount', 'inpost-international' ),
				'type'        => 'checkbox',
				'description' => esc_html__( 'If checked, free shipping would be available based on pre-discount order amount.', 'inpost-international' ),
				'default'     => 'no',
				'desc_tip'    => true,
			),
			'flat_rate'                              => array(
				'title'   => esc_html__( 'Flat rate', 'inpost-international' ),
				'type'    => 'checkbox',
				'label'   => esc_html__( 'Set a flat-rate shipping fee for the entire order.', 'inpost-international' ),
				'class'   => INPOST_INTL_PLUGIN_SLUG . '_flat_rate',
				'default' => 'yes',
			),
			'cost_per_order'                         => array(
				'title'             => esc_html__( 'Cost per order', 'inpost-international' ),
				'type'              => 'number',
				'custom_attributes' => array(
					'step' => 'any',
					'min'  => '0',
				),
				'class'             => INPOST_INTL_PLUGIN_SLUG . '_cost_per_order',
				'default'           => '',
				'desc_tip'          => esc_html__(
					'Set a flat-rate shipping for all orders',
					'inpost-international'
				),
				'placeholder'       => '0.00',
			),
			'tax_status'                             => array(
				'title'   => esc_html__( 'Tax status', 'inpost-international' ),
				'type'    => 'select',
				'class'   => 'wc-enhanced-select',
				'default' => 'none',
				'options' => array(
					'none'    => esc_html__( 'None', 'inpost-international' ),
					'taxable' => esc_html__( 'Taxable', 'inpost-international' ),
				),
			),

			array(
				'title'       => esc_html__( 'Rates table', 'inpost-international' ),
				'type'        => 'title',
				'description' => '',
				'id'          => 'section_general_settings',
				'class'       => INPOST_INTL_PLUGIN_SLUG . '_rates_table_title',
			),
			'based_on'                               => array(
				'title'       => esc_html__( 'Based on', 'inpost-international' ),
				'type'        => 'select',
				'desc_tip'    => esc_html__(
					'Select the method of calculating shipping cost. If the cost of shipping is to be calculated based on the weight of the cart and the products do not have a defined weight, the cost will be calculated incorrectly.',
					'inpost-international'
				),
				'description' => '',
				'class'       => 'wc-enhanced-select ' . INPOST_INTL_PLUGIN_SLUG . '_based_on',
				'options'     => array(
					'price'            => esc_html__( 'Price', 'inpost-international' ),
					'weight'           => esc_html__( 'Weight', 'inpost-international' ),
					'product_qty'      => esc_html__( 'Products qty', 'inpost-international' ),
					'parcel_templates' => esc_html__( 'Based on templates', 'inpost-international' ),
				),
			),
			'rates'                                  => array(
				'title'    => '',
				'type'     => 'rates',
				'class'    => INPOST_INTL_PLUGIN_SLUG . '_rates',
				'default'  => '',
				'desc_tip' => '',
			),
		);

		$settings = $this->add_shipping_classes_settings( $settings );

		$this->instance_form_fields = $settings;
		$this->form_fields          = $settings;
	}


	/**
	 * Generate button to upload custom logo
	 *
	 * @param string $key $key.
	 * @param array  $data $data.
	 *
	 * @return mixed
	 * @throws \Exception Exception.
	 */
	public function generate_logo_selected_html( $key, $data ) {
		$field_key = $this->get_field_key( $key );

		$defaults = array(
			'title'             => esc_html__( 'Upload custom logo', 'inpost-international' ),
			'disabled'          => false,
			'class'             => '',
			'css'               => '',
			'placeholder'       => '',
			'type'              => 'text',
			'desc_tip'          => false,
			'description'       => '',
			'custom_attributes' => array(),
		);

		$data = wp_parse_args( $data, $defaults );

		$value       = $this->get_instance_option( $key );
		$tooltip     = $this->get_tooltip_html( $data );
		$description = $this->get_description_html( $data );

		ob_start();

		inpost_intl_core()->locate_template(
			'shipping-method-choose-logo.php',
			array(
				'field_key'   => $field_key,
				'value'       => $value,
				'data'        => $data,
				'tooltip'     => $tooltip,
				'description' => $description,
			)
		);

		return ob_get_clean();
	}


	/**
	 * Add rate meta data
	 *
	 * @param array $args $args.
	 *
	 * @return void
	 */
	public function add_rate( $args = array() ): void {

		$args['meta_data'] = array(
			'inpost_order_sm_logo' => $this->get_instance_option( 'logo_selected' ),
			'inpost_delivery_terms' => $this->get_instance_option( 'delivery_terms' ),
		);

		parent::add_rate( $args );
	}


	/**
	 * Save custom rates settings
	 *
	 * @return void
	 */
	public function process_admin_options(): void {

		parent::process_admin_options();

		if ( ! isset( $_POST['inpost-international-save-rates-table-nonce'] ) ) {
			return;
		}

		if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['inpost-international-save-rates-table-nonce'] ) ), 'inpost-international-save-rates-table' ) ) {
			return;
		}

		if ( isset( $_POST['rates'] ) && is_array( $_POST['rates'] ) ) {

			$rates = map_deep( wp_unslash( $_POST['rates'] ), 'sanitize_text_field' );

			// Shipping method rates.
			$option_name = 'inpost_intl_' . $this->id . '_' . $this->instance_id . '_rates';
			update_option( $option_name, $rates, false );
		}

		if ( isset( $_POST['template_rates'] ) && is_array( $_POST['template_rates'] ) ) {

			$template_rates = map_deep( wp_unslash( $_POST['template_rates'] ), 'sanitize_text_field' );

			// Shipping method template rates.
			$option_name = 'inpost_intl_' . $this->id . '_' . $this->instance_id . '_template_rates';
			update_option( $option_name, $template_rates, false );
		}
	}

	/**
	 * Is free shipping setting must be applied
	 *
	 * @param array $package Package information.
	 *
	 * @return bool
	 */
	public function free_shipping_eligible_has_been_applied( $package ): bool {

		$total = WC()->cart->get_displayed_subtotal();

		if ( WC()->cart->display_prices_including_tax() ) {
			$total = $total - WC()->cart->get_discount_tax();
		}

		if ( 'no' === $this->ignore_discounts ) {
			$total = $total - WC()->cart->get_discount_total();
		}

		if ( ! empty( $this->free_shipping_cost )
			&& $this->free_shipping_cost <= $total
		) {

			// Add filter to allow disabling free shipping.
			$allow_free_shipping = apply_filters( 'inpost_intl_allow_free_shipping', true, $total, $package );

			if ( $allow_free_shipping ) {
				$add_free_ship_label = '';
				if ( 'yes' === $this->show_free_shipping_label ) {
					$add_free_ship_label = esc_html__( ' (free)', 'inpost-international' );
				}

				$add_rate = array(
					'id'    => $this->get_rate_id(),
					'label' => $this->title . ' ' . $add_free_ship_label,
					'cost'  => 0,
				);
				$this->add_rate( $add_rate );

				return true;
			}
		}

		return false;
	}


	/**
	 * Is fixed flat cost enabled in shipping method and must be applied
	 *
	 * @return bool
	 */
	public function is_flat_shipping_enabled_in_shipping_method(): bool {

		if ( 'yes' === $this->flat_rate ) {

			if ( (float) $this->cost_per_order > 0 ) {

				$add_rate = array(
					'id'    => $this->get_rate_id(),
					'label' => $this->title,
					'cost'  => $this->cost_per_order,
				);

			} else {

				$add_free_ship_label = '';
				if ( 'yes' === $this->show_free_shipping_label ) {
					$add_free_ship_label = esc_html__( ' (free)', 'inpost-international' );
				}

				$add_rate = array(
					'id'    => $this->get_rate_id(),
					'label' => $this->title . ' ' . $add_free_ship_label,
					'cost'  => 0,
				);
			}
			$this->add_rate( $add_rate );

			return true;
		}

		return false;
	}

	/**
	 * Get package weight
	 *
	 * @param array $items $items.
	 *
	 * @return float|int
	 */
	public function package_weight( $items ) {
		$weight = 0;
		foreach ( $items as $item ) {
			if ( ! empty( $item['data']->get_weight() ) ) {
				$weight += floatval( $item['data']->get_weight() ) * $item['quantity'];
			}
		}

		return $weight;
	}


	/**
	 * Get total items in cart
	 *
	 * @param array $items $items.
	 *
	 * @return int
	 */
	public function package_product_qty( $items ) {
		$package_product_qty = 0;
		foreach ( $items as $item ) {
			$package_product_qty += intval( $item['quantity'] );
		}
		return $package_product_qty;
	}


	/**
	 * Get package subtotal
	 *
	 * @param array $items $items.
	 *
	 * @return float|int
	 */
	public function package_subtotal( $items ) {
		$subtotal = 0;
		foreach ( $items as $item ) {
			$subtotal += $item['line_subtotal']
						+ $item['line_subtotal_tax'];
		}

		return $subtotal;
	}


	/**
	 * Calculate shipping based on custom table with rates
	 *
	 * @param array $package Package information.
	 */
	public function calculate_shipping_table_rate( $package ): void {

		// based on locker dimensions (A,B,C).
		if ( 'parcel_templates' === $this->based_on ) {

			$most_eligible_template = $this->get_max_gabaryt( $package );

			$cost = $this->get_cost_for_template( $this->get_rate_id(), $most_eligible_template );

			$add_rate = array(
				'id'      => $this->get_rate_id(),
				'label'   => $this->title,
				'cost'    => $cost,
				'package' => $package,
			);
			$this->add_rate( $add_rate );

			return;
		}

		$helper = new Helper();
		$rates  = $helper->get_rates_saved_for_shipping_method( $this->id, $this->instance_id );

		foreach ( $rates as $key => $rate ) {
			if ( empty( $rates[ $key ]['min'] ) || '' === trim( $rates[ $key ]['min'] ) ) {
				$rates[ $key ]['min'] = 0;
			}
			if ( empty( $rates[ $key ]['max'] ) || '' === trim( $rates[ $key ]['max'] ) ) {
				$rates[ $key ]['max'] = PHP_INT_MAX;
			}
		}

		$value = 0;
		if ( 'price' === $this->based_on ) {
			$value = $this->package_subtotal( $package['contents'] );
		}
		if ( 'product_qty' === $this->based_on ) {
			$value = $this->package_product_qty( $package['contents'] );
		}
		if ( 'weight' === $this->based_on ) {
			$value = $this->package_weight( $package['contents'] );
		}
		foreach ( $rates as $rate ) {
			if ( floatval( $rate['min'] ) <= $value && floatval( $rate['max'] ) >= $value ) {

				$add_rate = array(
					'id'    => $this->get_rate_id(),
					'label' => $this->title,
					'cost'  => $rate['cost'],
				);
				$this->add_rate( $add_rate );

				return;
			}
		}
	}

	/**
	 * Calculate shipping cost
	 *
	 * @param array $package Package information.
	 */
	public function calculate_shipping( $package = array() ): void {

		/**
		 * Order to caluclate shipping:
		 * 1) free shipping level
		 * 2) based on shipping class if exists
		 * 3) flat shipping settings (Cost per order)
		 * 4) table of costs based on weight/gabaryt
		 */

		if ( ! $this->free_shipping_eligible_has_been_applied( $package ) ) {

			$rate = array(
				'id'      => $this->get_rate_id(),
				'label'   => $this->title,
				'cost'    => 0,
				'package' => $package,
			);

			// Calculate the costs.
			$has_costs = false; // True when a cost is set. False if all costs are blank strings.
			$cost      = $this->get_option( 'cost' );

			if ( '' !== $cost ) {
				$has_costs    = true;
				$rate['cost'] = $this->evaluate_cost(
					$cost,
					array(
						'qty'  => $this->get_package_item_qty( $package ),
						'cost' => $package['contents_cost'],
					)
				);
			}

			// Add shipping class costs.
			$shipping_classes = WC()->shipping()->get_shipping_classes();

			if ( ! empty( $shipping_classes ) ) {
				$found_shipping_classes = $this->find_shipping_classes( $package );
				$highest_class_cost     = 0;

				foreach ( $found_shipping_classes as $shipping_class => $products ) {
					// Also handles BW compatibility when slugs were used instead of ids.
					$shipping_class_term = get_term_by( 'slug', $shipping_class, 'product_shipping_class' );
					$class_cost_string   = $shipping_class_term && $shipping_class_term->term_id ? $this->get_option( 'class_cost_' . $shipping_class_term->term_id, $this->get_option( 'class_cost_' . $shipping_class, '' ) ) : $this->get_option( 'no_class_cost', '' );

					if ( '' === $class_cost_string ) {
						continue;
					}

					$has_costs  = true;
					$class_cost = $this->evaluate_cost(
						$class_cost_string,
						array(
							'qty'  => array_sum( wp_list_pluck( $products, 'quantity' ) ),
							'cost' => array_sum( wp_list_pluck( $products, 'line_total' ) ),
						)
					);

					if ( 'class' === $this->type ) {
						$rate['cost'] += $class_cost;
					} else {
						$highest_class_cost = $class_cost > $highest_class_cost ? $class_cost : $highest_class_cost;
					}
				}

				if ( 'order' === $this->type && $highest_class_cost ) {
					$rate['cost'] += $highest_class_cost;
				}
			}

			if ( $has_costs ) {
				$this->add_rate( $rate );
			}

			/**
			 * Developers can add additional flat rates based on this one via this action since @version 2.4.
			 *
			 * Previously there were (overly complex) options to add additional rates however this was not user.
			 * friendly and goes against what Flat Rate Shipping was originally intended for.
			 */
			do_action( 'woocommerce_' . $this->id . '_shipping_add_rate', $this, $rate );

			if ( ! $has_costs ) {
				if ( ! $this->is_flat_shipping_enabled_in_shipping_method( $package ) ) {
					$this->calculate_shipping_table_rate( $package );
				}
			}
		}
	}


	/**
	 * Get max parcel size among the products in cart
	 *
	 * @param array $package Package information.
	 */
	public function get_max_gabaryt( array $package ): string {

		$biggest_template = 'default';

		if ( ! empty( $package['contents'] ) ) {

			$package_templates_in_cart = array();

			foreach ( $package['contents'] as $cart_item ) {
				$product_id                               = $cart_item['product_id'];
				$package_templates_in_cart[ $product_id ] = get_post_meta( $product_id, 'inpost_international_parcel_template', true );

			}

			if ( ! empty( $package_templates_in_cart ) ) {
				$helper           = new Helper();
				$biggest_template = $helper->get_biggest_template( $package_templates_in_cart );
			} else {
				return 'default';
			}
		}

		// by default.

		return $biggest_template;
	}





	/**
	 * Get items in package.
	 *
	 * @param array $package Package of items from cart.
	 *
	 * @return int
	 */
	public function get_package_item_qty( $package ) {
		$total_quantity = 0;
		foreach ( $package['contents'] as $item_id => $values ) {
			if ( $values['quantity'] > 0 && $values['data']->needs_shipping() ) {
				$total_quantity += $values['quantity'];
			}
		}

		return $total_quantity;
	}

	/**
	 * Finds and returns shipping classes and the products with said class.
	 *
	 * @param mixed $package Package of items from cart.
	 *
	 * @return array
	 */
	public function find_shipping_classes( $package ): array {

		$found_shipping_classes = array();

		foreach ( $package['contents'] as $item_id => $values ) {
			if ( $values['data']->needs_shipping() ) {
				$found_class = $values['data']->get_shipping_class();

				if ( ! isset( $found_shipping_classes[ $found_class ] ) ) {
					$found_shipping_classes[ $found_class ] = array();
				}

				$found_shipping_classes[ $found_class ][ $item_id ] = $values;
			}
		}

		return $found_shipping_classes;
	}


	/**
	 * Add settings to integrate with shipping classes
	 *
	 * @param array $settings $settings.
	 *
	 * @return array
	 */
	public function add_shipping_classes_settings( $settings ): array {
		$cost_desc        = esc_html__( 'Enter a cost (excl. tax) or sum, e.g. <code>10.00 * [qty]</code>.', 'inpost-international' ) . '<br/><br/>' . esc_html__( 'Use <code>[qty]</code> for the number of items, <br/><code>[cost]</code> for the total cost of items, and <code>[fee percent="10" min_fee="20" max_fee=""]</code> for percentage based fees.', 'inpost-international' );
		$shipping_classes = WC()->shipping()->get_shipping_classes();
		if ( ! empty( $shipping_classes ) ) {
			$settings['class_costs'] = array(
				'title'       => esc_html__( 'Shipping class costs', 'inpost-international' ),
				'type'        => 'title',
				'default'     => '',
				'description' => sprintf(
						/* translators: %s: URL for link. */
					__( 'These costs can optionally be added based on the <a href="%s">product shipping class</a>.', 'inpost-international' ),
					admin_url( 'admin.php?page=wc-settings&tab=shipping&section=classes' )
				),
			);
			foreach ( $shipping_classes as $shipping_class ) {
				if ( ! isset( $shipping_class->term_id ) ) {
					continue;
				}
				$settings[ 'class_cost_' . $shipping_class->term_id ] = array(
					/* translators: %s: shipping class name */
					'title'             => sprintf( __( '"%s" shipping class cost', 'inpost-international' ), esc_html( $shipping_class->name ) ),
					'type'              => 'text',
					'placeholder'       => esc_html__( 'N/A', 'inpost-international' ),
					'description'       => $cost_desc,
					'default'           => $this->get_option( 'class_cost_' . $shipping_class->slug ),
					// Before 2.5.0, we used slug here which caused issues with long setting names.
					'desc_tip'          => true,
					'sanitize_callback' => array( $this, 'sanitize_cost' ),
				);
			}

			$settings['no_class_cost'] = array(
				'title'             => esc_html__( 'No shipping class cost', 'inpost-international' ),
				'type'              => 'text',
				'placeholder'       => esc_html__( 'N/A', 'inpost-international' ),
				'description'       => $cost_desc,
				'default'           => '',
				'desc_tip'          => true,
				'sanitize_callback' => array( $this, 'sanitize_cost' ),
			);

			$settings['type'] = array(
				'title'   => esc_html__( 'Calculation type', 'inpost-international' ),
				'type'    => 'select',
				'class'   => 'wc-enhanced-select',
				'default' => 'class',
				'options' => array(
					'class' => esc_html__( 'Per class: Charge shipping for each shipping class individually', 'inpost-international' ),
					'order' => esc_html__( 'Per order: Charge shipping for the most expensive shipping class', 'inpost-international' ),
				),
			);
		}

		return $settings;
	}


	/**
	 * Evaluate a cost from a sum/string.
	 *
	 * @param string $sum Sum of shipping.
	 * @param array  $args Args, must contain `cost` and `qty` keys. Having `array()` as default is for back compat reasons.
	 *
	 * @return string
	 */
	protected function evaluate_cost( $sum, $args = array() ) {
		// Add warning for subclasses.
		if ( ! is_array( $args ) || ! array_key_exists( 'qty', $args ) || ! array_key_exists( 'cost', $args ) ) {
			wc_doing_it_wrong( __FUNCTION__, '$args must contain `cost` and `qty` keys.', '4.0.1' );
		}

		include_once WC()->plugin_path() . '/includes/libraries/class-wc-eval-math.php';

		// Allow 3rd parties to process shipping cost arguments.
		$args           = apply_filters( 'woocommerce_evaluate_shipping_cost_args', $args, $sum, $this );
		$locale         = localeconv();
		$decimals       = array(
			wc_get_price_decimal_separator(),
			$locale['decimal_point'],
			$locale['mon_decimal_point'],
			',',
		);
		$this->fee_cost = $args['cost'];

		// Expand shortcodes.
		add_shortcode( 'inpost_intl_fee', array( $this, 'fee' ) );

		$sum = do_shortcode(
			str_replace(
				array(
					'[qty]',
					'[cost]',
				),
				array(
					$args['qty'],
					$args['cost'],
				),
				$sum
			)
		);

		remove_shortcode( 'inpost_intl_fee', array( $this, 'fee' ) );

		// Remove whitespace from string.
		$sum = preg_replace( '/\s+/', '', $sum );

		// Remove locale from string.
		$sum = str_replace( $decimals, '.', $sum );

		// Trim invalid start/end characters.
		$sum = rtrim( ltrim( $sum, "\t\n\r\0\x0B+*/" ), "\t\n\r\0\x0B+-*/" );

		// Do the math.
		return $sum ? WC_Eval_Math::evaluate( $sum ) : 0;
	}



	/**
	 * Retrieves the shipping cost for a specific template size.
	 *
	 * Gets the shipping cost from saved shipping method rates for a specific
	 * template size. Handles both automated locker point and custom shipping
	 * method configurations.
	 *
	 * @since 1.0.0
	 *
	 * @param string $id              Shipping method ID with optional instance ID (format: 'method_id:instance_id').
	 * @param string $biggest_template The template size name to find the cost for.
	 *
	 * @uses get_option() To retrieve shipping method rates
	 *
	 * @return float|int The cost for the specified template size.
	 *                   Returns 0 if no matching rate is found.
	 *
	 * @example
	 * // Get cost for a specific shipping method and template
	 * $cost = $this->get_cost_for_template('inpost_international_automated_locker_point:1', 'Large');
	 *
	 * // Get cost for default shipping method
	 * $cost = $this->get_cost_for_template('inpost_international_automated_locker_point', 'Medium');
	 *
	 * Option name format:
	 * 'inpost_intl_{shipping_method_id}_{instance_id}_template_rates'
	 *
	 * Expected rates structure:
	 * [
	 *     [
	 *         'name' => 'Template Name',
	 *         'cost' => 10.00
	 *     ],
	 *     ...
	 * ]
	 */
	public function get_cost_for_template( $id, $biggest_template ) {

		$arr            = explode( ':', $id );
		$id             = ! empty( $arr[0] ) ? $arr[0] : 'inpost_international_automated_locker_point';
		$instance_id    = ! empty( $arr[1] ) ? $arr[1] : '';
		$sm_option_name = 'inpost_intl_' . $id . '_' . $instance_id . '_template_rates';

		$rates = get_option( $sm_option_name );
		if ( ! empty( $rates ) && is_array( $rates ) ) {
			$first_rate = reset( $rates );
			$cost       = 0;
			foreach ( $rates as $rate ) {
				if ( $rate['name'] === $biggest_template ) {
					$cost = $rate['cost'];
				}
			}
		}

		return $cost;
	}
}
