<?php
/**
 * Coordinates PPOM rendering, validation, cart data, order metadata, and upload finalization in WooCommerce.
 *
 * @package PPOM
 * @subpackage WooCommerce
 *
 * @see ppom_woocommerce_show_fields_on_product()
 * @see ppom_check_validation()
 * @see ppom_woocommerce_order_item_meta()
 * @see ppom_woocommerce_rename_files()
 */

if ( ! defined( 'ABSPATH' ) ) {
	die( 'Not Allowed.' );
}

// Rendering.
/**
 * Renders field if legacy input rendering mode is on
 *
 * @return void
 */
function ppom_woocommerce_show_fields() {

	global $product;

	$product_id = ppom_get_product_id( $product );

	ppom_woocommerce_show_fields_on_product( $product_id );
}


/**
 * Renders legacy PPOM fields for a product.
 *
 * @param int        $product_id Product ID.
 * @param array|null $args       Rendering arguments.
 *
 * @return string|void
 *
 * @see PPOM_Meta::__construct()
 * @see ppom_load_template()
 * @see ppom_woocommerce_template_base_inputs_rendering()
 */
function ppom_woocommerce_show_fields_on_product( $product_id, $args = null ) {

	$product = wc_get_product( $product_id );

	$product_id = ppom_get_product_id( $product );
	$ppom       = new PPOM_Meta( $product_id );

	if ( ! $ppom->fields ) {
		return '';
	}

	if ( ! $ppom->has_unique_datanames() ) {

		echo '<div class="error">' . esc_html__( 'Some of your fields has duplicated datanames, please fix it', 'woocommerce-product-addon' ) . '</div>';

		return;
	}


	$ppom_box_id = is_array( $ppom->meta_id ) ? implode( '-', $ppom->meta_id ) : $ppom->meta_id;
	$ppom_html   = '<div id="ppom-box-' . esc_attr( $ppom_box_id ) . '" class="ppom-wrapper">';

	if ( ppom_get_price_table_location() === 'before' ) {
		$ppom_html .= '<div id="ppom-price-container"></div>';
	}

	$template_vars = array(
		'ppom_settings'    => $ppom->ppom_settings,
		'product'          => $product,
		'ppom_fields_meta' => $ppom->fields,
		'ppom_id'          => $ppom->meta_id,
		'args'             => $args,
	);
	ob_start();
	ppom_load_template( 'render-fields.php', $template_vars );
	$ppom_html .= ob_get_clean();

	if ( ppom_get_price_table_location() === 'after' ) {
		$ppom_html .= '<div id="ppom-price-container"></div>';
	}

	// Clear fix
	$ppom_html .= '<div style="clear:both"></div>';   // Clear fix
	$ppom_html .= '</div>';   // Ends ppom-wrappper

	echo apply_filters( 'ppom_fields_html', $ppom_html, $product );
}

// Template Base Callback function
function ppom_woocommerce_inputs_template_base() {

	global $product;

	$product_id = ppom_get_product_id( $product );

	$args = apply_filters( 'ppom_rendering_template_args', array( 'enable_add_to_cart_id' => false ), $product );

	ppom_woocommerce_template_base_inputs_rendering( $product_id, $args );
}

/**
 * Renders template-based PPOM fields for a product.
 *
 * @param int        $product_id Product ID.
 * @param array|null $args       Rendering arguments.
 *
 * @return string|void
 *
 * @see PPOM_Form::ppom_fields_render()
 * @see ppom_load_input_templates()
 * @see ppom_woocommerce_show_fields_on_product()
 */
function ppom_woocommerce_template_base_inputs_rendering( $product_id, $args = null ) {

	$product = wc_get_product( $product_id );

	// @TODO: have to re-check abou args param for the Form class
	$form_obj = new PPOM_Form( $product, $args );

	// Check if PPOM fields is empty
	if ( ! $form_obj->has_ppom_fields() ) {
		return '';
	}

	$ppom_html     = '';
	$template_vars = array( 'form_obj' => $form_obj );

	ob_start();
	ppom_load_input_templates( 'frontend/ppom-fields.php', $template_vars );
	$ppom_html .= ob_get_clean();

	echo apply_filters( 'ppom_fields_html', $ppom_html, $product );
}

function ppom_woocommerce_load_scripts() {

	if ( ! is_product() ) {
		return '';
	}

	global $post;
	$product = wc_get_product( $post->ID );

	$ppom = new PPOM_Meta( $product->get_id() );


	if ( ! $ppom->fields ) {
		return '';
	}

	// Loading all required scripts/css for inputs like datepicker, fileupload etc
	ppom_hooks_load_input_scripts( $product );

	do_action( 'ppom_after_scripts_loaded', $ppom, $product );
}


// Validation.

/**
 * Validates PPOM fields during add to cart.
 *
 * Treats posted PPOM values as untrusted input and validates them against the
 * resolved field schema for the product.
 *
 * @param bool      $passed     Validation state from earlier callbacks.
 * @param int       $product_id Product ID.
 * @param int|float $qty        Requested quantity.
 *
 * @return bool
 *
 * @see ppom_check_validation()
 * @see PPOM_Meta::__construct()
 */
function ppom_woocommerce_validate_product( $passed, $product_id, $qty ) {

	$ppom = new PPOM_Meta( $product_id );
	if ( ! $ppom->ajax_validation_enabled ) {
		$passed = ppom_check_validation( $product_id, $_POST );
	}

	if ( ppom_get_price_mode() == 'legacy' && isset( $_POST['ppom']['fields'] ) ) {

		if ( ppom_is_price_attached_with_fields( $_POST['ppom']['fields'] ) &&
			empty( $_POST['ppom']['ppom_option_price'] )
		) {
			$error_message = __( 'Sorry, an error has occurred. Please enable JavaScript or contact site owner.', 'woocommerce-product-addon' );
			ppom_wc_add_notice( $error_message );
			$passed = false;

			return $passed;
		}
	}

	return $passed;
}

/**
 * Validates PPOM fields through the AJAX validation endpoint.
 *
 * @return void
 *
 * @see ppom_check_validation()
 * @see ppom_woocommerce_validate_product()
 */
function ppom_woocommerce_ajax_validate() {

	// ppom_pa($_POST); exit;
	$ppom_nonce            = $_REQUEST['ppom_nonce'];
	$validate_nonce_action = 'ppom_validating_action';
	if ( ! wp_verify_nonce( $ppom_nonce, $validate_nonce_action ) ) {

		$message  = sprintf( '<div class="woocommerce-error" role="alert">%s</div>', __( 'Error while validating, try again', 'woocommerce-product-addon' ) );
		$response = array(
			'status'  => 'error',
			'message' => $message,
		);
		wp_send_json( $response );
	}

	$errors_found = array();

	$product_id = intval( $_POST['ppom_product_id'] );
	$passed     = ppom_check_validation( $product_id, $_POST );

	$all_notices = wc_get_notices();
	wc_clear_notices();

	$response = array();
	if ( ! $passed ) {
		ob_start();
		foreach ( $all_notices as $type => $message ) {

			if ( $type != 'error' ) {
				continue;
			}
			wc_get_template(
				"notices/{$type}.php",
				array(
					'messages' => $message,
				)
			);
		}

		$all_notices = wc_kses_notice( ob_get_clean() );
		$response    = array(
			'status'  => 'error',
			'message' => $all_notices,
		);
	} else {
		$response = array( 'status' => 'success' );
	}
	// $all_notices = '<div class="">'.$all_notices.'</div>';
	// ppom_pa($all_notices);

	wp_send_json( $response );
}

/**
 * Validates posted PPOM fields against the product field schema.
 *
 * Reads posted values from `ppom[fields]`, skips hidden fields, and adds
 * WooCommerce notices for failed requirements.
 *
 * @param int   $product_id Product ID.
 * @param array $post_data  Posted request payload.
 * @param bool  $passed     Validation state from earlier checks.
 *
 * @return bool
 *
 * @see PPOM_Meta::get_fields()
 * @see ppom_has_posted_field_value()
 * @see ppom_woocommerce_add_cart_item_data()
 */
function ppom_check_validation( $product_id, $post_data, $passed = true ) {

	$ppom = new PPOM_Meta( $product_id );

	if ( ! $ppom->fields ) {
		return $passed;
	}

	$ppom_posted_fields = isset( $post_data['ppom']['fields'] ) ? $post_data['ppom']['fields'] : null;
	if ( ! $ppom_posted_fields ) {
		return $passed;
	}

	foreach ( $ppom->fields as $field ) {

		// ppom_pa($field);

		// Check field Visibility settings
		if ( ! ppom_is_field_visible( $field ) ) {
			continue;
		}

		if (
			empty( $field['data_name'] ) ||
			(
				( ! isset( $field['required'] ) || 'on' !== $field['required'] ) &&
				empty( $field['min_checked'] ) &&
				empty( $field['max_checked'] )
			)
		) {
			continue;
		}

		$passed = apply_filters( 'ppom_before_fields_validation', $passed, $field, $post_data, $product_id );

		$data_name = sanitize_key( $field['data_name'] );

		$title = isset( $field['title'] ) ? $field['title'] : '';

		// var_dump($data_name, ppom_is_field_hidden_by_condition($data_name));
		// Check if field is required by hidden by condition
		if ( ppom_is_field_hidden_by_condition( $data_name ) ) {
			continue;
		}

		$max_min_validation = ppom_posted_field_max_min_value_validation( $ppom_posted_fields, $field );
		if ( ! empty( $max_min_validation ) ) {
			ppom_wc_add_notice( $max_min_validation );
			$passed = false;
		} elseif ( isset( $field['required'] ) && 'on' === $field['required'] && ! ppom_has_posted_field_value( $ppom_posted_fields, $field ) ) {

			// Note: Checkbox is being validate by hook: ppom_has_posted_field_value
			// $error_message = isset($field['error_message']) ? $field['error_message'] : '';
			// $error_message = (isset($field['error_message']) && $field['error_message'] != '') ? $title.": ".$field['error_message'] : "{$title} is a required field";
			
			$error_message = ( isset( $field['error_message'] ) && $field['error_message'] != '' )
				? sprintf( '%1$s: %2$s', $title, $field['error_message'] )
				: sprintf(
					/* translators: %s: the name of the field. */
					__( '%s is a required field', 'woocommerce-product-addon' ),
					$title
				);
			$error_message = $error_message;
			$error_message = stripslashes( $error_message );
			ppom_wc_add_notice( $error_message );
			$passed = false;
		}
	}

	// ppom_pa($post_data); exit;

	return apply_filters( 'ppom_add_to_cart_validation', $passed, $ppom, $product_id );
}


// Cart data and session pricing.

/**
 * Stores posted PPOM data on the WooCommerce cart item.
 *
 * The posted payload remains untrusted and is revalidated and repriced later in
 * the cart and checkout lifecycle.
 *
 * @param array $cart       Cart item data.
 * @param int   $product_id Product ID.
 *
 * @return array
 *
 * @see ppom_check_validation()
 * @see ppom_price_controller()
 * @see ppom_make_meta_data()
 */
function ppom_woocommerce_add_cart_item_data( $cart, $product_id ) {

	if ( ! isset( $_POST['ppom'] ) ) {
		return $cart;
	}

	$ppom = new PPOM_Meta( $product_id );
	if ( ! $ppom->ppom_settings ) {
		return $cart;
	}

	WC()->cart->remove_cart_item( $_POST['ppom_cart_key'] );

	// ADDED WC BUNDLES COMPATIBILITY
	if ( function_exists( 'wc_pb_is_bundled_cart_item' ) && wc_pb_is_bundled_cart_item( $cart ) ) {
		return $cart;
	}

	// PPOM also saving cropped images under this filter.
	$ppom_posted_fields = apply_filters( 'ppom_add_cart_item_data', $_POST['ppom'], $_POST );
	$cart['ppom']       = $ppom_posted_fields;

	return $cart;
}

function ppom_woocommerce_update_cart_fees( $cart_items, $values ) {

	if ( empty( $cart_items ) ) {
		return $cart_items;
	}

	if ( ! isset( $values['ppom']['ppom_option_price'] ) ) {
		return $cart_items;
	}

	$wc_product = $cart_items['data'];
	$product_id = ppom_get_product_id( $wc_product );

	$ppom_meta_ids = '';
	// removing id field
	if ( ! empty( $values ['ppom'] ['fields']['id'] ) ) {
		$ppom_meta_ids = $values ['ppom'] ['fields']['id'];
		unset( $values ['ppom'] ['fields']['id'] );
	}

	// converting back to org price if Currency Switcher is used
	$ppom_item_org_price = ppom_hooks_convert_price_back( $wc_product->get_price() );
	// $ppom_item_org_price = $wc_product->get_price();

	$ppom_item_order_qty = floatval( $cart_items['quantity'] );

	// Getting option price
	$option_prices = json_decode( wp_unslash( $values['ppom']['ppom_option_price'] ), true );
	// ppom_pa($option_prices);
	$total_option_price = 0;
	$ppom_matrix_price  = 0;

	$ppom_quantities_price        = 0;
	$ppom_quantities_usebaseprice = false;
	$ppom_quantities_include_base = false;

	$ppom_total_quantities = 0;
	$ppom_total_discount   = 0;
	$ppon_onetime_cost     = 0;
	$ppomm_measures        = 1;    // meassure need to be multiple with each so it will be 1


	// If quantities field found then we need to get total quantity to get correct matrix price
	// if matrix is also used

	if ( $option_prices ) {
		foreach ( $option_prices as $option ) {
			if ( $option['apply'] == 'quantities' ) {
				$ppom_total_quantities += $option['quantity'];
				$ppom_item_order_qty    = $ppom_total_quantities;
			}
		}
	}


	// Check if price is set by matrix
	$matrix_found = ppom_get_price_matrix_chunk( $wc_product, $option_prices, $ppom_item_order_qty );
	// ppom_pa($matrix_found);

	// Calculating option prices
	if ( $option_prices ) {
		foreach ( $option_prices as $option ) {

			// Do not add if option is fixed/onetime
			// if( $option['apply'] != 'variable' ) continue;

			// ppom_get_field_option_price

			switch ( $option['apply'] ) {

				case 'variable':
					$option_price = $option['price'];
					// verify prices from server due to security
					if ( isset( $option['data_name'] ) && isset( $option['option_id'] ) ) {

						$option_price = ppom_get_field_option_price_by_id( $option, $wc_product, $ppom_meta_ids );
					}

					$total_option_price += wc_format_decimal( $option_price, wc_get_price_decimals() );
					break;

				case 'onetime':
					$option_price = $option['price'];
					// verify prices from server due to security
					if ( isset( $option['data_name'] ) && isset( $option['option_id'] ) ) {

						$option_price = ppom_get_field_option_price_by_id( $option, $wc_product, $ppom_meta_ids );
					}
					$ppon_onetime_cost += wc_format_decimal( $option_price, wc_get_price_decimals() );
					break;

				case 'quantities':
					$ppom_quantities_use_option_price = apply_filters( 'ppom_quantities_use_option_price', true, $option_prices );
					if ( $ppom_quantities_use_option_price ) {

						$quantity_price = $option['price'];

						// If matrix found now product org price will be set to matrix
						if ( ! empty( $matrix_found ) && ! isset( $matrix_found['discount'] ) ) {

							$quantity_price = $matrix_found['price'];

						}

						$ppom_quantities_price += wc_format_decimal( ( $quantity_price * $option['quantity'] ), wc_get_price_decimals() );
						// $ppom_total_quantities += $option['quantity'];
					}

					if ( ! empty( $option['include'] ) && $option['include'] == 'on' ) {
						$ppom_quantities_include_base = true;
					}
					break;

				case 'bulkquantity':
					// Note: May need to add matrix price like in quantites (above)

					$ppom_quantities_price += wc_format_decimal( ( $option['price'] * $option['quantity'] ), wc_get_price_decimals() );
					$ppom_quantities_price += isset( $option['base'] ) ? $option['base'] : 0;

					if ( isset( $option['usebase_price'] ) && $option['usebase_price'] == 'yes' ) {
						$ppom_quantities_usebaseprice = true;
					}
					break;

				// Fixed price addon
				case 'fixedprice':
					$ppom_item_org_price = $option['unitprice'];

					// Well, it should NOT be like this but have to do this. will see later.
					$ppom_item_order_qty = 1;
					break;

				case 'measure':
					$measer_qty       = isset( $option['qty'] ) ? intval( $option['qty'] ) : 0;
					$price_multiplier = isset( $option['price_multiplier'] ) ? floatval( $option['price_multiplier'] ) : 1;
					$option_price     = $option['price'];

					$ppomm_measures *= $measer_qty * $price_multiplier;


					break;

			}


			/**
			 * @since 15.4: Updating options weight
			 */
			if ( ppom_pro_is_installed() ) {
				$option_weight = ppom_get_field_option_weight_by_id( $option, $ppom_meta_ids );
				if ( $option_weight > 0 ) {
					$new_weight = $wc_product->get_weight() + $option_weight;
					$wc_product->set_weight( $new_weight );
				}
			}
		}
	}


	// ppom_pa($matrix_found);
	if ( ! empty( $matrix_found ) ) {

		// Check that it's not a discount matrix
		if ( ! isset( $matrix_found['discount'] ) ) {
			$ppom_item_org_price = $matrix_found['price'];
		} else {

			// Discount matrix found
			if ( ! empty( $matrix_found['percent'] ) ) {

				$total_with_options = $ppom_item_org_price + $total_option_price + $ppon_onetime_cost;

				// Check wheather to apply on Both (Base+Options) or only Base
				if ( $matrix_found['discount'] == 'both' ) {

					// Also adding quantities price if used
					$total_price_to_be_discount = $total_with_options + $ppom_quantities_price;

					$price_after_precent = ppom_get_amount_after_percentage( $total_price_to_be_discount, $matrix_found['percent'] );
				} elseif ( $matrix_found['discount'] == 'base' ) {

					$total_price_to_be_discount = $ppom_item_org_price + $ppom_quantities_price;
					$price_after_precent        = ppom_get_amount_after_percentage( $total_price_to_be_discount, $matrix_found['percent'] );
				}

				$ppom_total_discount += $price_after_precent;
			} else {
				/**
				 * when discount is in PRICE not Percent then applied to whole price Base+Option)
				 * so need to get per unit discount
				 */

				/*
				** @since 16.8
				** When each variation has own quantity, then cart quantity is disabled only one price is set
				** not indivisual
				**/
				if ( ! $ppom_quantities_usebaseprice ) {

					$ppom_total_discount += $matrix_found['price'];
				} else {
					$discount_per_unit    = $matrix_found['price'] / $ppom_item_order_qty;
					$ppom_total_discount += $discount_per_unit;
				}
			}
		}
	}


	if ( $ppom_quantities_price > 0 ) {

		if ( ! $ppom_quantities_include_base ) {
			// $ppom_item_org_price = ($ppom_item_org_price * $ppom_total_quantities);
			$ppom_item_org_price = 0;

			// when base price is NOT included the quantity is updated so it must be multiplied by options
			$total_option_price = ( $total_option_price * $ppom_total_quantities );
		}
	}

	// If measures found, Multiply it with options
	if ( $ppomm_measures > 0 ) {
		// $total_option_price = $total_option_price * $ppomm_measures;
		$ppom_item_org_price = $ppom_item_org_price * $ppomm_measures;
	}


	// var_dump($ppom_total_discount);
	// var_dump($ppom_item_org_price);
	// var_dump($total_option_price);
	// var_dump($ppom_quantities_price);


	$cart_line_total = ( $ppom_item_org_price + $total_option_price + $ppom_quantities_price - $ppom_total_discount );

	$cart_line_total = apply_filters( 'ppom_cart_line_total', $cart_line_total, $cart_items, $values );

	$wc_product->set_price( $cart_line_total );

	return $cart_items;
}

function ppom_calculate_totals_from_session( $cart ) {
	$cart->calculate_totals();
}


function ppom_woocommerce_add_fixed_fee( $cart ) {

	$fee_no = 1;
	foreach ( $cart->get_cart() as $item ) {

		if ( empty( $item['ppom']['ppom_option_price'] ) ) {
			continue;
		}

		// Getting option price
		$option_prices = json_decode( wp_unslash( $item['ppom']['ppom_option_price'] ), true );

		if ( $option_prices ) {
			foreach ( $option_prices as $fee ) {

				if ( $fee['apply'] != 'onetime' ) {
					continue;
				}


				$label = $fee['product_title'] . ': ' . $fee['label'];
				$label = apply_filters( 'ppom_fixed_fee_label', $label, $fee, $item );

				$taxable   = ( isset( $fee['taxable'] ) && $fee['taxable'] == 'on' ) ? true : false;
				$fee_price = $fee['price'];

				if ( ! empty( $fee['without_tax'] ) ) {
					$fee_price = $fee['without_tax'];
				}

				// if(  'incl' === get_option( 'woocommerce_tax_display_shop' ) ) {
				// $taxable = false;
				// }

				$fee_price = apply_filters( 'ppom_cart_fixed_fee', $fee_price, $fee, $cart );

				if ( $fee_price != 0 ) {
					$cart->fees_api()->add_fee(
						array(
							'id'      => 'ppom_fee_' . $fee_no,
							'name'    => esc_html( $label ),
							'amount'  => (float) $fee_price,
							'taxable' => $taxable,
						)
					);
					++$fee_no;
				}
			}
		}
	}
}

// Show fixed fee in mini cart
function ppom_woocommerce_mini_cart_fixed_fee() {

	if ( ! WC()->cart->get_fees() ) {
		return '';
	}

	$fixed_fee_html = '<table>';
	foreach ( WC()->cart->get_fees() as $fee ) {

		$item_fee = $fee->amount;
		if ( WC()->cart->display_prices_including_tax() && $fee->taxable ) {

			$item_fee = $fee->total + $fee->tax;
		}
		$item_fee        = apply_filters( 'ppom_option_price', $item_fee );
		$fixed_fee_html .= '<tr>';
		$fixed_fee_html .= '<td class="subtotal-text">' . esc_html( $fee->name );
		'</td>';
		$fixed_fee_html .= '<td class="subtotal-price">' . wc_price( $item_fee ) . '</td>';
		$fixed_fee_html .= '</tr>';
	}

	$fixed_fee_html .= '<tr><td colspan="2">' . __( 'Total will be calculated in the cart', 'woocommerce-product-addon' ) . '</td></tr>';
	$fixed_fee_html .= '</table>';

	echo apply_filters( 'ppom_mini_cart_fixed_fee', $fixed_fee_html );
}

function ppom_woocommerce_add_item_meta( $item_meta, $cart_item ) {

	if ( ! isset( $cart_item['ppom']['fields'] ) ) {
		return $item_meta;
	}


	// ADDED WC BUNDLES COMPATIBILITY
	if ( function_exists( 'wc_pb_is_bundled_cart_item' ) && wc_pb_is_bundled_cart_item( $cart_item ) ) {
		return $item_meta;
	}

	$ppom_meta = ppom_make_meta_data( $cart_item );
	// ppom_pa($ppom_meta);

	foreach ( $ppom_meta as $key => $meta ) {

		$hidden     = isset( $meta['hidden'] ) ? $meta['hidden'] : false;
		$meta_name  = isset( $meta['name'] ) ? $meta['name'] : '';
		$meta_value = isset( $meta['value'] ) ? $meta['value'] : '';
		$display    = isset( $meta['display'] ) ? $meta['display'] : $meta_value;
		$meta_price = isset( $meta['price'] ) ? $meta['price'] : 0;
		$meta_price = apply_filters( 'ppom_option_price', $meta_price );
		if ( $key == 'ppom_has_quantities' ) {
			$hidden = true;
		}

		$allowed_input_fields = array( 'text', 'textarea', 'number' );
		$is_allowed_field     = in_array( $meta['type'], $allowed_input_fields, true );

		if ( $is_allowed_field && '' === $display ) {
			// Allow 0 and '0', skip only truly empty values
			continue;
		} elseif ( ! $is_allowed_field && empty( $display ) ) {
			// For other fields, treat 0 as empty as well
			continue;
		}

		if ( ! empty( $meta_name ) ) {

			if ( ! is_scalar( $meta_value ) ) {
				$meta_value = wp_json_encode( $meta_value );
			}

			if ( apply_filters( 'ppom_show_option_price_cart', false ) && ! empty( $meta_price ) ) {
				$meta_value .= ' (' . wc_price( $meta_price ) . ')';
			}

			$meta_key = stripslashes( $meta_name );

			// WPML
			$meta_key = ppom_wpml_translate( $meta_key, 'PPOM' );

			$item_meta[] = array(
				'name'    => wp_strip_all_tags( $meta_key ),
				'value'   => $meta_value,
				'hidden'  => $hidden,
				'display' => $display,
			);
		} else {
			$item_meta[] = array(
				'name'    => ( $key ),
				'value'   => $meta,
				'hidden'  => $hidden,
				'display' => $display,
			);
		}
	}

	return $item_meta;
}

// alter price on shop page if price matrix found
function ppom_woocommerce_alter_price( $price, $product ) {

	$product_id = ppom_get_product_id( $product );

	if ( class_exists( 'sitepress' ) ) {
		$default_lang = apply_filters( 'wpml_default_language', null );
		$product      = wc_get_product( apply_filters( 'wpml_object_id', $product->get_id(), 'product', true, $default_lang ) );
	}

	$price_matrix_found = ppom_has_field_by_type( $product_id, 'pricematrix' );
	if ( empty( $price_matrix_found ) && apply_filters( 'ppom_hide_product_price_if_zero', true, $product ) ) {
		if ( $product->get_price() <= 0 ) {
			return '';
		}
	}

	if ( empty( $price_matrix_found ) ) {
		return $price;
	}

	$from_pice = '';
	$to_price  = '';

	if ( ! in_array( $product->get_type(), array( 'variable', 'grouped', 'external' ) ) ) {

		$price_range = array();

		foreach ( $price_matrix_found as $meta ) {

			// ppom_pa($meta);

			if ( ! ppom_is_field_visible( $meta ) ) {
				continue;
			}

			if ( $meta['type'] == 'pricematrix' ) {

				$options = $meta['options'];
				$ranges  = ppom_convert_options_to_key_val( $options, $meta, $product );
				// ppom_pa($ranges);

				if ( isset( $meta['discount'] ) && $meta['discount'] == 'on' ) {

					$last_discount = end( $ranges );
					$least_price   = $last_discount['price'];

					if ( ! empty( $last_discount['percent'] ) ) {
						$max_discount = $last_discount['percent'];
						$least_price  = ppom_get_amount_after_percentage( $product->get_price(), $max_discount );
					}

					$least_price = floatval( $product->get_price() ) - $least_price;
					$least_price = wc_format_decimal( $least_price, wc_get_price_decimals() );
					$least_price = apply_filters( 'ppom_option_price', $least_price );
					$price       = wc_price( $least_price ) . '-' . $price;
				} else {

					foreach ( $ranges as $range ) {
						$price_range[] = $range['price'];
					}

					if ( ! empty( $price_range ) ) {

						$from_pice = min( $price_range );
						$to_price  = max( $price_range );
						$price     = wc_format_price_range( $from_pice, $to_price );
					}
				}
			}
		}
	}

	return apply_filters( 'ppom_loop_matrix_price', $price, $from_pice, $to_price );
}

/*
function ppom_hide_variation_price_html($show, $parent, $variation) {

	$product_id = $parent->get_id();
	$ppom       = new PPOM_Meta( $product_id );

	if( $ppom->is_exists && $ppom->price_display != 'hide' ) {
		$show = false;
	}

	return $show;

}*/

// Set default quantity for price matrix
function ppom_woocommerce_product_default_quantity( $args, $product ) {

	if ( ! is_product() ) {
		return $args;
	}

	$product_id = ppom_get_product_id( $product );
	$ppom       = new PPOM_Meta( $product_id );
	if ( ! $ppom->is_exists ) {
		return $args;
	}

	$ppom_matrix_found = ppom_has_field_by_type( $product_id, 'pricematrix' );

	if ( $ppom_matrix_found ) {

		$price_matrix = reset( $ppom_matrix_found );
		// If it is Discount Matrix, do not set min quantity
		// if( isset($meta['discount']) && $meta['discount'] == 'on' ) continue;
		$options = $price_matrix['options'];
		$ranges  = ppom_convert_options_to_key_val( $options, $price_matrix, $product );
		if ( ! empty( $ranges ) ) {
			$first_range         = reset( $ranges );
			$qty_ranges          = explode( '-', $first_range['raw'] );
			$args['input_value'] = $qty_ranges[0];
		}
	}

	return $args;
}

// Set min quantity for price matrix
function ppom_woocommerce_set_min_quantity( $min_quantity, $product ) {

	$product_id = ppom_get_product_id( $product );
	$ppom       = new PPOM_Meta( $product_id );
	if ( ! $ppom->is_exists ) {
		return $min_quantity;
	}

	$ppom_matrix_found = ppom_has_field_by_type( $product_id, 'pricematrix' );
	if ( $ppom_matrix_found ) {
		foreach ( $ppom_matrix_found as $meta ) {

			// If it is Discount Matrix, do not set min quantity
			// if( isset($meta['discount']) && $meta['discount'] == 'on' ) continue;
			$options = $meta['options'];
			$ranges  = ppom_convert_options_to_key_val( $options, $meta, $product );

			if ( empty( $ranges ) ) {
				continue;
			}

			$first_range  = reset( $ranges );
			$qty_ranges   = explode( '-', $first_range['raw'] );
			$min_quantity = $qty_ranges[0];
		}
	}

	// Check min quantity for variations
	$ppom_quantities_found = ppom_has_field_by_type( $product_id, 'quantities' );
	if ( $ppom_quantities_found ) {
		foreach ( $ppom_quantities_found as $qty ) {
			if ( ! $qty['min_qty'] ) {
				continue;
			}

			if ( $min_quantity < floatval( $qty['min_qty'] ) ) {
				$min_quantity = $qty['min_qty'];
			}
		}
	}

	return $min_quantity;
}

// Set max quantity for price matrix
function ppom_woocommerce_set_max_quantity( $max_quantity, $product ) {

	$product_id = ppom_get_product_id( $product );
	$ppom       = new PPOM_Meta( $product_id );
	if ( ! $ppom->is_exists ) {
		return $max_quantity;
	}

	$last_range = array();

	$ppom_matrix_found = ppom_has_field_by_type( $product_id, 'pricematrix' );

	if ( $ppom_matrix_found ) {
		foreach ( $ppom_matrix_found as $meta ) {

			// If it is Discount Matrix, do not set max quantity
			if ( isset( $meta['discount'] ) && $meta['discount'] == 'on' ) {
				continue;
			}

			$options = $meta['options'];
			// ppom_pa($options);
			$ranges = ppom_convert_options_to_key_val( $options, $meta, $product );

			if ( empty( $ranges ) ) {
				continue;
			}

			$last_range   = end( $ranges );
			$qty_ranges   = explode( '-', $last_range['raw'] );
			$max_quantity = $qty_ranges[1];
		}
	}

	// Check min quantity for variations
	$ppom_quantities_found = ppom_has_field_by_type( $product_id, 'quantities' );
	if ( $ppom_quantities_found ) {
		foreach ( $ppom_quantities_found as $qty ) {
			if ( ! $qty['max_qty'] ) {
				continue;
			}

			if ( $max_quantity < floatval( $qty['max_qty'] ) ) {
				$max_quantity = $qty['max_qty'];
			}
		}
	}

	return $max_quantity;
}

// Set quantity step for price matrix
function ppom_woocommerce_set_quantity_step( $quantity_step, $product ) {

	$product_id = ppom_get_product_id( $product );
	$ppom       = new PPOM_Meta( $product_id );
	if ( ! $ppom->is_exists ) {
		return $quantity_step;
	}

	$last_range = array();

	$ppom_matrix_found = ppom_has_field_by_type( $product_id, 'pricematrix' );
	if ( $ppom_matrix_found ) {
		foreach ( $ppom_matrix_found as $meta ) {

			$quantity_step = empty( $meta['qty_step'] ) ? 1 : $meta['qty_step'];
		}
	}

	return $quantity_step;
}

// When quantities is used then reset quantity to 1
function ppom_woocommerce_add_to_cart_quantity( $quantity, $product_id ) {

	if ( ppom_reset_cart_quantity_to_one( $product_id ) ) {
		$quantity = 1;
	}

	return $quantity;
}

// It is change cart quantity label
function ppom_woocommerce_control_cart_quantity_legacy( $quantity, $cart_item_key ) {

	$cart_item = WC()->cart->get_cart_item( $cart_item_key );

	// ppom_pa($cart_item)
	if ( ! isset( $cart_item['ppom']['ppom_option_price'] ) &&
		! isset( $cart_item['ppom']['ppom_pricematrix'] ) ) {
		return $quantity;
	}

	// Getting option price
	$option_prices       = json_decode( wp_unslash( $cart_item['ppom']['ppom_option_price'] ), true );
	$ppom_has_quantities = 0;
	// ppom_pa($option_prices);

	if ( empty( $option_prices ) ) {
		return $quantity;
	}

	foreach ( $option_prices as $option ) {

		if ( isset( $option['include'] ) && $option['include'] == '' ) {
			if ( isset( $option['quantity'] ) ) {
				$ppom_has_quantities += intval( $option['quantity'] );
			}
		} elseif ( isset( $option['include'] ) && $option['include'] == 'on' ) {
			$ppom_has_quantities = 1;
		}
	}

	// var_dump($ppom_has_quantities);
	// If no quantity updated then return default
	$ppom_quantitiles_allow_update_cart = apply_filters( 'ppom_quantities_allow_cart_update', false, $option_prices );
	if ( $ppom_has_quantities != 0 && ! $ppom_quantitiles_allow_update_cart ) {
		$quantity = '<span class="ppom-cart-quantity">' . $ppom_has_quantities . '</span>';
	}

	return $quantity;
}

function ppom_woocommerce_control_cart_quantity( $quantity, $cart_item_key ) {

	$cart_item = WC()->cart->get_cart_item( $cart_item_key );

	if ( ! isset( $cart_item['ppom']['fields'] ) ) {
		return $quantity;
	}

	$ppom_fields_post = $cart_item['ppom']['fields'];
	$product_id       = $cart_item['product_id'];

	if ( ppom_is_cart_quantity_updatable( $product_id ) ) {
		return $quantity;
	}

	$ppom_has_quantities = ppom_price_get_total_quantities( $ppom_fields_post, $product_id );

	// var_dump(!$ppom_quantitiles_allow_update_cart);
	// If no quantity updated then return default
	$ppom_quantitiles_allow_update_cart = apply_filters( 'ppom_quantities_allow_cart_update', false, $ppom_fields_post );
	if ( $ppom_has_quantities != 0 && ! $ppom_quantitiles_allow_update_cart ) {
		$quantity = '<span class="ppom-cart-quantity">' . $ppom_has_quantities . '</span>';
	}

	return $quantity;
}

// Control subtotal when quantities input used.
function ppom_woocommerce_item_subtotal( $item_subtotal, $cart_item, $cart_item_key ) {

	if ( ! isset( $cart_item['ppom']['ppom_option_price'] ) ) {
		return $item_subtotal;
	}

	// Getting option price.
	$option_prices = json_decode( wp_unslash( $cart_item['ppom']['ppom_option_price'] ), true );

	if ( empty( $option_prices ) ) {
		return $item_subtotal;
	}

	$price = 0;
	foreach ( $option_prices as $option ) {
		$option       = ppom_translation_options( $option );
		$option_price = isset( $option['price'] ) ? $option['price'] : 0;
		if ( 0 === $option_price || ( ! isset( $option['apply'] ) || 'onetime' !== $option['apply'] ) ) {
			continue;
		}
		$price = isset( $option['discount'] ) && $option['discount'] > 0 ? $option['discount'] : $option_price;
		if ( ! empty( $price ) ) {
			$price = apply_filters( 'ppom_option_price', $price );
			$price = floatval( wp_strip_all_tags( $price ) );
		}
	}

	if ( 0 === $price ) {
		return $item_subtotal;
	}
	$product_id    = $cart_item['product_id'];
	$quantity      = $cart_item['quantity'];
	$product_data  = new WC_Product( $product_id );
	$product_price = floatval( $product_data->get_price() ) * $quantity;
	$item_subtotal = $product_price + $price;
	return ppom_price( $item_subtotal );
}

function ppom_woocommerce_control_checkout_quantity( $quantity, $cart_item, $cart_item_key ) {

	// ppom_pa($cart_item);
	if ( ! isset( $cart_item['ppom']['fields'] ) ) {
		return $quantity;
	}

	$ppom_fields_post = $cart_item['ppom']['fields'];
	$product_id       = $cart_item['product_id'];

	if ( ppom_is_cart_quantity_updatable( $product_id ) ) {
		return $quantity;
	}

	$ppom_has_quantities = ppom_price_get_total_quantities( $ppom_fields_post, $product_id );

	// If no quantity updated then return default
	if ( $ppom_has_quantities > 0 ) {
		$quantity = '<strong class="product-quantity">' . sprintf( '&times; %s', $ppom_has_quantities ) . '</strong>';
	}

	return $quantity;
}

function ppom_woocommerce_control_oder_item_quantity( $quantity, $item ) {

	$ppom_has_quantities = 0;

	$product_id = $item->get_product_id();

	$ppom_fields_post = wc_get_order_item_meta( $item->get_id(), '_ppom_fields' );
	if ( ! isset( $ppom_fields_post['fields'] ) ) {
		return $quantity;
	}

	$ppom_fields_post = $ppom_fields_post['fields'];

	if ( ppom_is_cart_quantity_updatable( $product_id ) ) {
		return $quantity;
	}

	$ppom_has_quantities = ppom_price_get_total_quantities( $ppom_fields_post, $product_id );

	if ( $ppom_has_quantities > 0 ) {
		$quantity = '<strong class="product-quantity">' . sprintf( '&times; %s', $ppom_has_quantities ) . '</strong>';
	}

	return $quantity;
}

function ppom_woocommerce_control_email_item_quantity( $quantity, $item ) {

	$ppom_has_quantities = 0;

	$product_id = $item->get_product_id();

	$ppom_fields_post = wc_get_order_item_meta( $item->get_id(), '_ppom_fields' );
	if ( ! isset( $ppom_fields_post['fields'] ) ) {
		return $quantity;
	}

	$ppom_fields_post = $ppom_fields_post['fields'];

	if ( ppom_is_cart_quantity_updatable( $product_id ) ) {
		return $quantity;
	}

	$ppom_has_quantities = ppom_price_get_total_quantities( $ppom_fields_post, $product_id );

	if ( $ppom_has_quantities > 0 ) {
		$quantity = '<strong class="product-quantity">' . esc_html( $ppom_has_quantities ) . '</strong>';
	}

	return $quantity;
}

function ppom_woocommerce_control_order_item_quantity( $quantity, $item ) {

	$ppom_has_quantities = 0;

	$product_id = $item->get_product_id();

	$ppom_fields_post = wc_get_order_item_meta( $item->get_id(), '_ppom_fields' );
	if ( ! isset( $ppom_fields_post['fields'] ) ) {
		return $quantity;
	}

	$ppom_fields_post = $ppom_fields_post['fields'];

	if ( ppom_is_cart_quantity_updatable( $product_id ) ) {
		return $quantity;
	}

	$ppom_has_quantities = ppom_price_get_total_quantities( $ppom_fields_post, $product_id );

	if ( $ppom_has_quantities > 0 ) {
		$quantity = $ppom_has_quantities;
	}

	return $quantity;
}

function ppom_woocommerce_cart_update_validate( $cart_validated, $cart_item_key, $values, $quantity ) {

	$max_quantity = ppom_get_cart_item_max_quantity( $values );

	if ( ! is_null( $max_quantity ) && $quantity > intval( $max_quantity ) ) {

		$cart_validated = false;
		wc_add_notice(
			sprintf(
				// translators: %d: the number of maximum quantity.
				__( 'Sorry, maximum quantity is %d.', 'woocommerce-product-addon' ),
				$max_quantity
			),
			'error'
		);
	}

	return $cart_validated;
}


// Order persistence.

/**
 * Stores PPOM metadata on an order line item.
 *
 * Saves formatted display values as line-item meta and preserves the raw PPOM
 * payload in `_ppom_fields` for later formatting and replay.
 *
 * @param WC_Order_Item_Product $item          Order line item.
 * @param string                $cart_item_key Cart item key.
 * @param array                 $values        Cart item values.
 * @param WC_Order              $order         Order being created.
 *
 * @return void
 *
 * @see ppom_make_meta_data()
 * @see ppom_get_field_meta_by_dataname()
 * @see ppom_woocommerce_order_value()
 */
function ppom_woocommerce_order_item_meta( $item, $cart_item_key, $values, $order ) {

	if ( ! isset( $values ['ppom']['fields'] ) ) {
		return;
	}
	// ADDED WC BUNDLES COMPATIBILITY
	if ( function_exists( 'wc_pb_is_bundled_cart_item' ) && wc_pb_is_bundled_cart_item( $values ) ) {
		return;
	}

	$ppom_meta = ppom_make_meta_data( $values, 'order' );
	// ppom_pa($item->get_product_id()); exit;

	$cropper_fields = array();
	foreach ( $ppom_meta as $key => $meta ) {

		if ( ! isset( $meta['value'] ) ) {
			continue;
		}

		// WPML
		$meta_key = ppom_wpml_translate( $key, 'PPOM' );

		$meta_value = isset( $meta['display'] ) ? $meta['display'] : $meta['value'];
		$item->update_meta_data( $key, $meta_value );

		// Since 24.5: Removing the image cropper base64 data
		// Reason: https://clients.najeebmedia.com/forums/topic/order-search-in-woocommerce-not-working/
		$meta = ppom_get_field_meta_by_dataname( $item->get_product_id(), $key );
		if ( isset( $meta['type'] ) && $meta['type'] == 'cropper' ) {
			$cropper_fields[] = $key;
		}
	}

	$no_base64                = array_diff_key( $values ['ppom']['fields'], array_flip( $cropper_fields ) );
	$values['ppom']['fields'] = $no_base64;

	// Since 15.2, saving all fields as another meta
	$item->update_meta_data( '_ppom_fields', $values ['ppom'] );
}

// Changing order item meta key to label
function ppom_woocommerce_order_key( $display_key, $meta, $item ) {

	if ( $item->get_type() != 'line_item' ) {
		return $display_key;
	}

	$field_meta = ppom_get_field_meta_by_dataname( $item->get_product_id(), $display_key );
	if ( isset( $field_meta['title'] ) && $field_meta['title'] != '' ) {
		$display_key = stripslashes( $field_meta['title'] );
	}

	return $display_key;
}

/**
 * Formats PPOM order item meta for display.
 *
 * @param mixed              $display_value Formatted value from WooCommerce.
 * @param object|null        $meta          Order item meta object.
 * @param WC_Order_Item|null $item   Order item.
 *
 * @return mixed
 *
 * @see ppom_generate_html_for_files()
 * @see ppom_get_field_meta_by_dataname()
 * @see ppom_woocommerce_order_item_meta()
 */
function ppom_woocommerce_order_value( $display_value, $meta = null, $item = null ) {

	if ( is_null( $item ) ) {
		return $display_value;
	}

	if ( $item->get_type() != 'line_item' ) {
		return $display_value;
	}

	$field_meta = ppom_get_field_meta_by_dataname( $item->get_product_id(), $meta->key );

	// if( ! isset($field_meta['type']) ) return $display_value;

	$input_type = isset( $field_meta['type'] ) ? $field_meta['type'] : '';

	switch ( $input_type ) {

		case 'file':
		case 'cropper':
			/**
			 * File upload and croppers now save only filename in meta
			 * seperated by commas, now here we will build it's html to show thumbs in item orde
			 *
			 * @since: 10.10
			 */
			$display_value = ppom_generate_html_for_files( $meta->value, $input_type, $item );
			break;

		case 'image':
			$display_value = $meta->value;
			break;

		default:
			// Important hook: changing order value format using local hooks
			// Also being used for export order lite
			$display_value = apply_filters( 'ppom_order_display_value', $display_value, $meta, $item );
			break;

	}

	return $display_value;
}


// Hiding some ppom meta like ppom_has_quantities
function ppom_woocommerce_hide_order_meta( $formatted_meta, $order_item ) {

	if ( empty( $formatted_meta ) ) {
		return $formatted_meta;
	}

	$ppom_meta_searching = $formatted_meta;
	// ppom_has_quantities
	foreach ( $ppom_meta_searching as $meta_id => $meta_data ) {

		if ( $meta_data->key == 'ppom_has_quantities' ) {
			unset( $formatted_meta[ $meta_id ] );
		}
	}

	return $formatted_meta;
}

// Upload finalization.

/**
 * Moves uploaded PPOM files into the confirmed order directory.
 *
 * File names and destination paths are resolved on the server from the cart
 * payload and the saved field schema.
 *
 * @param int      $order_id    Order ID.
 * @param mixed    $posted_data Posted checkout data.
 * @param WC_Order $order       Processed order.
 *
 * @return void
 *
 * @see ppom_get_dir_path()
 * @see ppom_get_field_meta_by_dataname()
 * @see ppom_get_file_download_url()
 */
function ppom_woocommerce_rename_files( $order_id, $posted_data, $order ) {

	global $woocommerce;

	// getting product id in cart
	$cart = WC()->cart->get_cart();

	// ppom_pa($cart); exit;


	// since 8.1, files will be send to email as attachment

	// ppom_pa($cart); exit;
	foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {

		// ppom_pa($cart_item); exit;
		if ( ! isset( $cart_item['ppom']['fields'] ) ) {
			continue;
		}

		$product_id      = $cart_item['product_id'];
		$all_moved_files = array();

		foreach ( $cart_item['ppom']['fields'] as $key => $values ) {

			if ( $key == 'id' ) {
				continue;
			}

			$field_meta = ppom_get_field_meta_by_dataname( $product_id, $key );
			if ( ! $field_meta ) {
				continue;
			}

			$field_type  = $field_meta['type'];
			$field_label = isset( $field_meta['title'] ) ? $field_meta['title'] : $field_meta['data_name'];
			$moved_files = array();

			if ( $field_type == 'file' || $field_type == 'cropper' ) {

				$base_dir_path      = ppom_get_dir_path();
				$confirm_dir        = 'confirmed/' . $order_id;
				$confirmed_dir_path = ppom_get_dir_path( $confirm_dir );
				$edits_dir_path     = ppom_get_dir_path( 'edits' );

				foreach ( $values as $file_id => $file_data ) {
					if ( ! isset( $file_data['org'] ) ) {
						continue;
					}
					$file_name    = $file_data['org'];
					$file_cropped = isset( $file_data['cropped'] ) ? true : false;

					$new_filename     = ppom_file_get_name( $file_name, $product_id, $cart_item );
					$source_file      = $base_dir_path . $file_name;
					$destination_path = $confirmed_dir_path . $new_filename;


					if ( file_exists( $destination_path ) ) {
						break;
					}

					/*
					$moved_files[] = array('path' => $destination_path,
											'file_name' => $file_name,
											'product_id' => $product_id);*/

					if ( file_exists( $source_file ) ) {

						if ( ! rename( $source_file, $destination_path ) ) {
							die( 'Error while re-naming order image ' . $source_file );
						}
					}

					// renaming edited files
					$source_file_edit      = $edits_dir_path . $file_name;
					$destination_path_edit = '';

					$file_edited = false;
					if ( file_exists( $source_file_edit ) ) {

						$destination_path_edit = $edits_dir_path . $new_filename;
						if ( ! rename( $source_file_edit, $destination_path_edit ) ) {
							die( 'Error while re-naming order image ' . $source_file_edit );
						} else {
							$file_edited = true;
						}
					}

					$moved_files[] = array(
						'path'           => $destination_path,
						'file_name'      => $file_name,
						'file_label'     => $field_label,
						'file_cropped'   => $file_cropped,
						'file_edited'    => $file_edited,
						'file_edit_path' => $destination_path_edit,
						'product_id'     => $product_id,
						'field_name'     => $key,
					);

					// $moved_files['file_edited'] = $file_edited;
				}

				$all_moved_files[ $key ] = $moved_files;
			}
		}

		do_action( 'ppom_after_files_moved', $all_moved_files, $order_id, $order );
	}
}

/**
 * Responsible from the adding a support for Order Again functionality in the WooCommerce My Account -> Order View page.
 * The method adds PPOM Fields to the given order item from the provided order. (Clones the PPOM data of data order item to the new cart)
 *
 * @param  array                  $cart_item_data Current custom item data.
 * @param  \WC_Order_Item_Product $item Order Item Product
 * @param  \WC_Order              $order
 * @return void
 */
function ppom_wc_order_again_compatibility( $cart_item_data, $item, $order ) {
	$ppom_data = $item->get_meta( '_ppom_fields' );

	if ( is_array( $ppom_data ) && array_key_exists( 'fields', $ppom_data ) ) {
		$cart_item_data['ppom'] = $ppom_data;
	}

	return $cart_item_data;
}

/**
 * Outputs the formatted meta data for WooCommerce order items.
 *
 * @param int                    $item_id The item ID.
 * @param \WC_Order_Item_Product $item The order item object.
 */
function ppom_woocommerce_order_item_meta_html( $item_id, $item ) {
	$formatted_meta = $item->get_formatted_meta_data();

	$strings        = array();
	$meta_item_html = '';
	$output_args    = apply_filters(
		'ppom_woocommerce_item_meta_args',
		array(
			'before'       => '<ul class="wc-item-meta"><li>',
			'after'        => '</li></ul>',
			'separator'    => '</li><li>',
			'label_before' => '<strong class="wc-item-meta-label">',
			'label_after'  => ':</strong> ',
		)
	);
	foreach ( $formatted_meta as $meta ) {
		$strings[] = $output_args['label_before'] . wp_kses_post( $meta->display_key ) . $output_args['label_after'] . ppom_woocommerce_order_value( $meta->display_value, $meta, $item );
	}

	if ( $strings ) {
		$meta_item_html = $output_args['before'] . implode( $output_args['separator'], $strings ) . $output_args['after'];
	}
	echo wp_kses_post( $meta_item_html );
}

/**
 * Check if the email improvements feature is enabled.
 *
 * @return bool
 */
function ppom_wc_email_improvements_enabled() {
	return 'yes' === get_option( 'woocommerce_feature_email_improvements_enabled', 'no' );
}

/**
 * Outputs the formatted meta data for invoice or packing slips.
 *
 * @param string                 $html HTML of the item meta data 
 * @param \WC_Order_Item_Product $item The order item object.
 * @param array                  $args arguments for display the html.
 */
function ppom_invoice_packing_slips_html( $html, $item, $args = array() ) {
	$strings = array();
	$args    = wp_parse_args(
		$args,
		array(
			'before'       => '<ul class="wc-item-meta"><li>',
			'after'        => '</li></ul>',
			'separator'    => '</li><li>',
			'echo'         => true,
			'autop'        => false,
			'label_before' => '<strong class="wc-item-meta-label">',
			'label_after'  => ':</strong> ',
		)
	);

	foreach ( $item->get_all_formatted_meta_data() as $meta_id => $meta ) {
		$meta_value = ppom_woocommerce_order_value( $meta->display_value, $meta, $item );
		$value      = $args['autop'] ? wp_kses_post( $meta_value ) : wp_kses_post( make_clickable( trim( $meta_value ) ) );
		$strings[]  = $args['label_before'] . wp_kses_post( $meta->display_key ) . $args['label_after'] . $value;
	}

	if ( $strings ) {
		$html = $args['before'] . implode( $args['separator'], $strings ) . $args['after'];
	}

	return $html;
}
