<?php

namespace Inspire_Labs\Alsendo_Connect;

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


use WC_Countries;

class Helper {



	/**
	 * Retrieves the full county/state name from its code.
	 *
	 * Uses WooCommerce countries data to translate a state/county code
	 * into its full name. Returns the original code if no match is found.
	 *
	 * @param string $state_code   The state/county code to translate.
	 * @param string $country_code The country code (default 'RO' for Romania).
	 *
	 * @return string The full county/state name, or the original code if not found.
	 */
	public function get_full_county_name( $state_code, $country_code = 'RO' ) {
		// Get WC_Countries instance.
		$wc_countries = new WC_Countries();

		// Get states for the country.
		$states = $wc_countries->get_states( $country_code );

		// Return the full state/county name if it exists
		if ( isset( $states[ $state_code ] ) ) {
			return $states[ $state_code ];
		}

		// Return the code if no match found.
		return $state_code;
	}

	/**
	 * Get default pickup date for Ecolet courier pickup.
	 *
	 * If "Allow same-day pickup (send today)" is enabled, returns today's date.
	 * Otherwise returns the next business day (Mon-Fri).
	 *
	 * @return string Date in Y-m-d format.
	 */
	private function get_ecolet_default_pickup_date(): string {
		$timestamp = (int) current_time( 'timestamp' );

		// Same-day pickup: today.
		if ( 'yes' === get_option( 'alsendo_connect_settings_general_ecolet_day_to_send' ) ) {
			return date( 'Y-m-d', $timestamp );
		}

		// Otherwise: next business day.
		$timezone = function_exists( 'wp_timezone' ) ? wp_timezone() : new \DateTimeZone( 'UTC' );
		$dt       = ( new \DateTimeImmutable( '@' . $timestamp ) )->setTimezone( $timezone )->modify( '+1 day' );

		while ( in_array( (int) $dt->format( 'w' ), array( 0, 6 ), true ) ) { // 0=Sun, 6=Sat
			$dt = $dt->modify( '+1 day' );
		}

		return $dt->format( 'Y-m-d' );
	}

	/**
	 * Get the next business day (Mon-Fri) after a given date.
	 *
	 * @param string $date_ymd Date in Y-m-d format.
	 * @return string Date in Y-m-d format (next business day).
	 */
	private function get_next_business_day_from_ymd( string $date_ymd ): string {
		$timezone = function_exists( 'wp_timezone' ) ? wp_timezone() : new \DateTimeZone( 'UTC' );
		$dt       = \DateTimeImmutable::createFromFormat( 'Y-m-d', $date_ymd, $timezone );

		// If parsing fails, fall back to "+1 day" from current date.
		if ( ! ( $dt instanceof \DateTimeImmutable ) ) {
			$dt = ( new \DateTimeImmutable( 'now', $timezone ) )->modify( '+1 day' );
		} else {
			$dt = $dt->modify( '+1 day' );
		}

		while ( in_array( (int) $dt->format( 'w' ), array( 0, 6 ), true ) ) { // 0=Sun, 6=Sat
			$dt = $dt->modify( '+1 day' );
		}

		return $dt->format( 'Y-m-d' );
	}


	/**
	 * Retrieves order meta data with fallback options.
	 *
	 * @param int    $order_id The order ID.
	 * @param string $meta_key The meta key to retrieve.
	 * @return mixed|null The meta value or null if not found.
	 *
	 * @since 1.0.2
	 * @access public
	 */
	public function get_woo_order_meta( $order_id, $meta_key ) {

		$res = null;

		if ( ! $order_id ) {
			return null;
		}

		$order = wc_get_order( $order_id );
		if ( ! $order || is_wp_error( $order ) ) {
			return null;
		}

		$res = $order->get_meta( $meta_key );

		if ( empty( $res ) ) {
			$res = get_post_meta( $order_id, $meta_key, true );
		}

		if ( ! $res && 'alsendo_connect_wc_order' === $meta_key ) {
			$res = $this->get_woo_order_meta( $order_id, '_apaczka' );
		}

		if ( ! $res && 'alsendo_connect_delivery_point' === $meta_key ) {
			$res = $this->get_woo_order_meta( $order_id, 'apaczka_delivery_point' );
		}

		return $res;
	}


	/**
	 * Retrieves parcel content description based on the specified tag type.
	 *
	 * Generates a parcel content string from order data according to the tag parameter.
	 * Supports 'order_id', 'product_id', 'product_name', or custom string values.
	 * For product names, includes quantity suffix when greater than 1.
	 *
	 * @param int    $order_id The WooCommerce order ID.
	 * @param string $tag      The content type tag ('order_id', 'product_id', 'product_name', or custom string).
	 *
	 * @return string The parcel content description, or empty string if order is invalid.
	 */
	public function get_parcel_content( $order_id, $tag ) {

		$parcel_content = '';

		$wc_order = wc_get_order( $order_id );

		if ( ! $wc_order || is_wp_error( $wc_order ) ) {
			return $parcel_content;
		}

		if ( 'order_id' === $tag ) {
			$parcel_content = $order_id;

		} elseif ( 'product_id' === $tag ) {
			$product_ids = array();

			// Get all items from the order.
			$items = $wc_order->get_items();

			// Loop through each item and get the product ID.
			foreach ( $items as $item ) {
				$product_id = $item->get_product_id();
				if ( $product_id ) {
					$product_ids[] = $product_id;
				}
			}

			// Create a comma-separated string of product IDs.
			$parcel_content = implode( ',', $product_ids );
		} elseif ( 'product_name' === $tag ) {
			$product_names = array();

			// Get all items from the order.
			$items = $wc_order->get_items();

			// Loop through each item and get the product name.
			foreach ( $items as $item ) {
				$product_name = $item->get_name();
				if ( $product_name ) {
					// Add quantity if more than 1.
					$quantity = $item->get_quantity();
					if ( $quantity > 1 ) {
						$product_name .= ' (' . $quantity . 'pcs)';
					}

					$product_names[] = $product_name;
				}
			}

			// Create a comma-separated string of product names.
			$parcel_content = implode( ', ', $product_names );

		} else {
			if ( ! empty( $tag ) && is_string( $tag ) ) {
				$parcel_content = $tag;
			}
		}

		// Limit string length.
		/*if (strlen($parcel_content) > 100) {
			$parcel_content = substr($parcel_content, 0, 97) . '...';
		}*/

		return $parcel_content;
	}



	/**
	 * Extracts and compiles shipment data from a WooCommerce order for Ecolet processing.
	 *
	 * Retrieves comprehensive shipping information including sender and receiver details,
	 * parcel specifications, additional services, courier type, and parcel data.
	 * Includes debug logging for parcel type, courier type, and parcels information.
	 * Falls back to billing address if shipping address is not available.
	 *
	 * @param int    $order_id     The WooCommerce order ID.
	 * @param string $carrier_id   The carrier identifier.
	 * @param bool   $use_template Whether to use template settings for data extraction.
	 *
	 * @return array Associative array containing sender, receiver, parcel, services, courier, and parcels data, or empty array if order is invalid.
	 */
	public function ecolet_extract_data_from_order( $order_id, $carrier_id, $use_template ) {

		$order = wc_get_order( $order_id );

		if ( ! $order || is_wp_error( $order ) ) {
			return array();
		}

		$courier_type = $this->ecolet_get_bulk_courier_type( $order_id, $carrier_id, $use_template );

		$sender_details   = $this->ecolet_get_bulk_sender_details( $order_id, $carrier_id, $use_template, $courier_type );
		$receiver_details = $this->ecolet_get_bulk_receiver_details( $order_id, $carrier_id );

		$parcel_type         = $this->ecolet_get_bulk_parcel_type( $order_id, $carrier_id, $use_template );
		$additional_services = $this->ecolet_get_bulk_additional_services( $order_id, $carrier_id );

		$parcels = $this->ecolet_get_bulk_parcels( $order_id, $carrier_id, $use_template );

		$receiver_line_1 = '';
		if ( ! empty( $order->get_shipping_address_1() ) ) {
			$receiver_line_1 = $order->get_shipping_address_1();
		} elseif ( ! empty( $order->get_billing_address_1() ) ) {
			$receiver_line_1 = $order->get_billing_address_1();
		}

		$receiver_line_2 = '';
		if ( ! empty( $order->get_shipping_address_2() ) ) {
			$receiver_line_2 = $order->get_shipping_address_2();
		} elseif ( ! empty( $order->get_billing_address_2() ) ) {
			$receiver_line_2 = $order->get_billing_address_2();
		}

		return array(
			'sender'               => $sender_details,
			'receiver'             => $receiver_details,
			'receiver_woo_address' => array(
				'line_1' => $receiver_line_1,
				'line_2' => $receiver_line_2,
			),
			'parcel'               => $parcel_type,
			'additional_services'  => $additional_services,
			'courier'              => $courier_type,
			'parcels'              => $parcels,
		);
	}




	/**
	 * Retrieves sender details for Ecolet bulk shipment processing.
	 *
	 * Compiles sender information from plugin settings including company name, address,
	 * contact details, and locality ID. Handles phone number formatting by removing spaces.
	 * For self-pickup methods, includes dispatch point mapping information when applicable.
	 *
	 * @param int    $order_id     The WooCommerce order ID.
	 * @param string $carrier_id   The carrier identifier.
	 * @param string $use_template The template identifier to use for data extraction, or 'alsendo-connect-main-config' for main settings.
	 *
	 * @return array Associative array containing complete sender details including address, contact info, and optional map point data.
	 */
	public function ecolet_get_bulk_sender_details( $order_id, $carrier_id, $use_template, $courier_type ) {

		$sender_template_values = array();
		if ( 'alsendo-connect-main-config' !== $use_template ) {
			$selected_sender_template = get_option( 'alsendo_connect_settings_general_select_sender_template', '' );
			if ( ! empty( $selected_sender_template ) ) {
				$sender_templates_json = ( new Sender_Settings_Templates_Helper() )->get_all_templates_json();
				$sender_templates      = json_decode( $sender_templates_json, true );
				if ( ! empty( $sender_templates[ $selected_sender_template ]['options'] ) && is_array( $sender_templates[ $selected_sender_template ]['options'] ) ) {
					$sender_template_values = $sender_templates[ $selected_sender_template ]['options'];
				}
			}
		}

		$get_sender_value = static function ( string $key, $default = '' ) use ( $sender_template_values ) {
			$option_key = 'alsendo_connect_settings_general_sender_' . $key;
			if ( isset( $sender_template_values[ $option_key ] ) && '' !== $sender_template_values[ $option_key ] ) {
				return $sender_template_values[ $option_key ];
			}

			return get_option( $option_key, $default );
		};

		$sender_phone = $get_sender_value( 'phone' );
		$sender_phone = str_replace( ' ', '', $sender_phone );
		$sender_phone = trim( $sender_phone );

		$sender = array(
			'name'           => $get_sender_value( 'company_name' ),
			'country'        => $get_sender_value( 'country' ),
			'county'         => $get_sender_value( 'province' ),
			'locality'       => $get_sender_value( 'city' ),
			'locality_id'    => '',
			'postal_code'    => $get_sender_value( 'postal_code' ),
			'street_name'    => $get_sender_value( 'street' ),
			'street_number'  => $get_sender_value( 'building_number' ),
			'block'          => $get_sender_value( 'block', '' ),
			'entrance'       => $get_sender_value( 'entrance', '' ),
			'floor'          => $get_sender_value( 'floor', '' ),
			'flat'           => $get_sender_value( 'apartment_number' ),
			'contact_person' => $get_sender_value( 'contact_person' ),
			'email'          => $get_sender_value( 'email' ),
			'phone'          => $sender_phone,
			'has_map_point'  => '',
			'map_point_id'   => '',
		);

		$ecolet             = new Ecolet();
		$county_full_name   = $this->get_full_county_name( $sender['county'], $sender['country'] );
		$sender_locality_id = $ecolet->get_locality_id( $sender['country'], $sender['locality'], $county_full_name, $sender['postal_code'], 'sender' );

		$sender['locality_id'] = $sender_locality_id;

		$courier_pickup_type = ! empty( $courier_type['pickup']['type'] ) ? $courier_type['pickup']['type'] : '';

		if ( 'self' === $courier_pickup_type ) {
			$order_placed_data = alsendo_connect()->get_delivery_point_meta_data( $order_id );
			$service_supplier  = ! empty( $order_placed_data['apm_supplier'] ) ? $order_placed_data['apm_supplier'] : null;

			// pre-defined by choice of byuer during checkout.
			if ( $service_supplier ) {
				$sender_point = $this->get_ecolet_merchant_default_point( $service_supplier );
				if ( $sender_point ) {
					$sender['has_map_point'] = 1;
					$sender['map_point_id']  = $sender_point;
				}
			}
		}

		return $sender;
	}



	/**
	 * Retrieves receiver details for Ecolet bulk shipment processing from order data.
	 *
	 * Extracts and compiles receiver information from WooCommerce order, prioritizing
	 * shipping address over billing address for most fields. Handles address parsing
	 * by splitting address lines into components (street name/number, block, entrance, floor, flat).
	 * Formats phone number by removing spaces. Includes delivery point mapping if available.
	 * Retrieves locality ID for Romanian and Bulgarian addresses.
	 *
	 * @param int    $order_id   The WooCommerce order ID.
	 * @param string $carrier_id The carrier identifier.
	 *
	 * @return array Associative array containing complete receiver details including address, contact info, and optional map point data, or empty array if order is invalid.
	 */
	public function ecolet_get_bulk_receiver_details( $order_id, $carrier_id ) {

		$order = wc_get_order( $order_id );

		if ( ! $order || is_wp_error( $order ) ) {
			return array();
		}

		$ecolet = new Ecolet();

		$shipping_name    = $order->get_shipping_company();
		$shipping_contact = '';
		if ( empty( $shipping_name ) ) {
			$shipping_name    = $order->get_shipping_first_name() . ' '
								. $order->get_shipping_last_name();
			$shipping_contact = $order->get_shipping_first_name() . ' '
								. $order->get_shipping_last_name();

		} else {
			$shipping_contact = $order->get_shipping_first_name() . ' '
								. $order->get_shipping_last_name();
		}

		$receiver_name = '';
		if ( ! empty( $order->get_billing_company() ) ) {
			$receiver_name = $order->get_billing_company();
		} elseif ( ! empty( $order->get_shipping_company() ) ) {
			$receiver_name = $order->get_shipping_company();
		} else {
			$receiver_name = $shipping_contact;
		}

		$receiver_country = '';
		if ( ! empty( $order->get_shipping_country() ) ) {
			$receiver_country = $order->get_shipping_country();
		} elseif ( ! empty( $order->get_billing_country() ) ) {
			$receiver_country = $order->get_billing_country();
		}

		$receiver_province = '';
		if ( ! empty( $order->get_shipping_state() ) ) {
			$receiver_province = $order->get_shipping_state();
		} elseif ( ! empty( $order->get_billing_state() ) ) {
			$receiver_province = $order->get_billing_state();
		}

		$receiver_city = '';
		if ( ! empty( $order->get_shipping_city() ) ) {
			$receiver_city = $order->get_shipping_city();
		} elseif ( ! empty( $order->get_billing_city() ) ) {
			$receiver_city = $order->get_billing_city();
		}

		$receiver_postal_code = '';
		if ( ! empty( $order->get_shipping_postcode() ) ) {
			$receiver_postal_code = $order->get_shipping_postcode();
		} elseif ( ! empty( $order->get_billing_postcode() ) ) {
			$receiver_postal_code = $order->get_billing_postcode();
		}

		$receiver_email = '';
		if ( ! empty( $order->get_billing_email() ) ) {
			$receiver_email = $order->get_billing_email();
		}

		$receiver_phone = '';
		if ( ! empty( $order->get_shipping_phone() ) ) {
			$receiver_phone = $order->get_shipping_phone();
		} elseif ( ! empty( $order->get_billing_phone() ) ) {
			$receiver_phone = $order->get_billing_phone();
		}

		$receiver_phone = $this->ecolet_phone_validation( $receiver_phone, $receiver_country );

		$delivery_point     = null;
		$has_delivery_point = false;
		$order_placed_data  = alsendo_connect()->get_delivery_point_meta_data( $order_id );
		if ( ! empty( $order_placed_data['apm_access_point_id'] ) ) {
			$delivery_point     = $order_placed_data['apm_access_point_id'];
			$has_delivery_point = 1;
		}

		$receiver_street = '';
		if ( ! empty( $order->get_shipping_address_1() ) ) {
			$receiver_street = $order->get_shipping_address_1();
		} elseif ( ! empty( $order->get_billing_address_1() ) ) {
			$receiver_street = $order->get_billing_address_1();
		}
		if ( ! empty( $receiver_street ) ) {
			$receiver_street = $ecolet::split_line_one( $receiver_street, $order_id );
		}

		$receiver_street_name   = ! empty( $receiver_street['name'] ) ? $receiver_street['name'] : '';
		$receiver_street_number = ! empty( $receiver_street['number'] ) ? $receiver_street['number'] : '';

		$line_2 = '';
		if ( ! empty( $order->get_shipping_address_2() ) ) {
			$line_2 = $order->get_shipping_address_2();
		} elseif ( ! empty( $order->get_billing_address_2() ) ) {
			$line_2 = $order->get_billing_address_2();
		}
		if ( ! empty( $line_2 ) ) {
			$line_2 = $ecolet::split_line_two( $line_2, $receiver_street, $order_id );
		} else {
			$line_2 = $ecolet::split_line_two( '', $receiver_street, $order_id );
		}

		$block    = ! empty( $line_2['block'] ) ? $line_2['block'] : '';
		$entrance = ! empty( $line_2['entrance'] ) ? $line_2['entrance'] : '';
		$floor    = ! empty( $line_2['floor'] ) ? strtoupper( $line_2['floor'] ) : '';
		$flat     = ! empty( $line_2['flat'] ) ? $line_2['flat'] : '';

		$receiver_locality_id = null;
		if ( 'RO' === strtoupper( $receiver_country ) || 'BG' === strtoupper( $receiver_country ) ) {
			$county_full_name     = $this->get_full_county_name( $receiver_province, $receiver_country );
			$receiver_locality_id = $ecolet->get_locality_id( $receiver_country, $receiver_city, $county_full_name, $receiver_postal_code, 'receiver' );
		}

		$receiver = array(
			'name'           => $receiver_name,
			'country'        => $receiver_country,
			'county'         => $receiver_province,
			'locality'       => $receiver_city,
			'locality_id'    => $receiver_locality_id,
			'postal_code'    => $receiver_postal_code,
			'street_name'    => $receiver_street_name,
			'street_number'  => $receiver_street_number,
			'block'          => $block,
			'entrance'       => $entrance,
			'floor'          => $floor,
			'flat'           => $flat,
			'contact_person' => $shipping_contact,
			'email'          => $receiver_email,
			'phone'          => $receiver_phone,
			'has_map_point'  => $has_delivery_point,
			'map_point_id'   => $delivery_point,
		);

		return $receiver;
	}


	/**
	 * Retrieves parcel type configuration for Ecolet bulk shipment processing.
	 *
	 * Determines parcel type, shape (standard/nonstandard), and observations based on
	 * either main configuration settings or a specified package template. Handles custom
	 * text content or dynamic content generation based on order data (order ID, product ID,
	 * or product name). Falls back to main settings when template is 'alsendo-connect-main-config'.
	 *
	 * @param int    $order_id     The WooCommerce order ID.
	 * @param string $carrier_id   The carrier identifier.
	 * @param string $use_template The template identifier to use for parcel configuration, or 'alsendo-connect-main-config' for main settings.
	 *
	 * @return array Associative array containing parcel type, shape, and observations.
	 */
	public function ecolet_get_bulk_parcel_type( $order_id, $carrier_id, $use_template ) {
		/*'parcel'              => array(
			'type'         => $parcel_type,
			'shape'        => $data['package_properties']['is_nstd'] === 'yes' ? 'nonstandard' : 'standard',
			'observations' => $data['additional_options']['comment'],
		),*/

		$package_templates_json = ( new Gateway_Settings_Templates_Helper() )->get_all_templates_json();
		$package_templates      = json_decode( $package_templates_json, true );

		if ( ! empty( $use_template ) && ! empty( $package_templates[ $use_template ] ) ) {
			$template_data = $package_templates[ $use_template ];
			$type          = 0;
			$shape         = 'standard';
			$observations  = array();

			$type  = ! empty( $template_data['options']['alsendo_connect_settings_general_parcel_type'] ) ? $template_data['options']['alsendo_connect_settings_general_parcel_type'] : '';
			$shape = 'yes' === $template_data['options']['alsendo_connect_settings_general_is_nstd'] ? 'nonstandard' : 'standard';

			$package_content = '';

			$tag = ! empty( $template_data['options']['alsendo_connect_settings_general_package_contents'] ) ? $template_data['options']['alsendo_connect_settings_general_package_contents'] : '';

			if ( ! empty( $tag ) ) {
				if ( 'custom_text' === $tag ) {
					$package_content = ! empty( $template_data['options']['alsendo_connect_settings_general_custom_text_content'] ) ? $template_data['options']['alsendo_connect_settings_general_custom_text_content'] : '';
				} else {
					$package_content = $this->get_parcel_content( $order_id, $tag );
				}
			}

			$data['type']         = $type;
			$data['shape']        = $shape;
			$data['observations'] = $package_content;
		} else {
			$data['type']  = get_option( 'alsendo_connect_settings_general_parcel_type' );
			$data['shape'] = 'yes' === get_option( 'alsendo_connect_settings_general_parcel_type' ) ? 'nonstandard' : 'standard';

			$package_content = '';
			$observations    = ! empty( get_option( 'alsendo_connect_settings_general_package_contents' ) ) ? get_option( 'alsendo_connect_settings_general_package_contents' ) : '';
			if ( ! empty( $observations ) ) {
				if ( 'custom_text' === $observations ) {
					$package_content = get_option( 'alsendo_connect_settings_general_custom_text_content', '' );
				} else {
					$package_content = $this->get_parcel_content( $order_id, $observations );
				}
			}

			$data['observations'] = $package_content;

		}

		return $data;
	}


	/**
	 * Retrieves additional services configuration for Ecolet bulk shipment processing.
	 *
	 * Returns a predefined array of available additional services with all statuses
	 * set to false by default. Services include COD, open package, ROD, ROP,
	 * Saturday delivery, SMS notification, swap, and EPOD.
	 *
	 * @param int    $order_id   The WooCommerce order ID.
	 * @param string $carrier_id The carrier identifier.
	 *
	 * @return array Associative array of additional services with status flags.
	 */
	public function ecolet_get_bulk_additional_services( $order_id, $carrier_id ) {

		$data = array(
			'cod'               => array(
				'status' => false,
			),
			'open_package'      => array(
				'status' => false,
			),
			'rod'               => array(
				'status' => false,
			),
			'rop'               => array(
				'status' => false,
			),
			'saturday_delivery' => array(
				'status' => false,
			),
			'sms_notify'        => array(
				'status' => false,
			),
			'swap'              => array(
				'status' => false,
			),
			'epod'              => array(
				'status' => false,
			),
		);

		$order = wc_get_order( $order_id );

		if ( ! $order || is_wp_error( $order ) ) {
			return $data;
		}

		$payment_method = $order->get_payment_method();

		if ( 'cod' === $payment_method ) {
			$data['cod']['status'] = 1;
			$data['cod']['amount'] = $order->get_total();
		}

		return $data;
	}



	/**
	 * Retrieves courier type and pickup configuration for Ecolet bulk shipment processing.
	 *
	 * Determines courier service, pickup method (courier or self), pickup date, and time
	 * based on either main configuration settings or a specified package template.
	 * For self-pickup methods (SELF_ prefixed), sets pickup date and time to null.
	 * For courier pickup, defaults to next day with configured pickup time.
	 *
	 * @param int    $order_id     The WooCommerce order ID.
	 * @param string $carrier_id   The carrier identifier.
	 * @param string $use_template The template identifier to use for courier configuration, or 'alsendo-connect-main-config' for main settings.
	 *
	 * @return array Associative array containing service slug, pickup details (type, date, time), and contract ID.
	 */
	public function ecolet_get_bulk_courier_type( $order_id, $carrier_id, $use_template ) {
		/*
		 * 'courier'             => array(
			'service'     => $ecolet->get_service_slug( $service_id ),
			'pickup'      => array(
				'type' => strtolower( $pickup_method ),
				'date' => $data['package_properties']['pickup_date'],
				'time' => gmdate( 'H:i', strtotime( $data['package_properties']['pickup_hour_to'] ) ),
			),
			'contract_id' => isset( $data['contract_id'] ) ? $data['contract_id'] : null,
		)
		*/

		$ecolet = new Ecolet();

		$package_templates_json = ( new Gateway_Settings_Templates_Helper() )->get_all_templates_json();
		$package_templates      = json_decode( $package_templates_json, true );

		if ( ! empty( $use_template ) && ! empty( $package_templates[ $use_template ] ) ) {
			$template_data = $package_templates[ $use_template ];
			$pickup_method = '';
			$pickup_date   = $this->get_ecolet_default_pickup_date();
			$time          = '';

			$pickup_method = ! empty( $template_data['options']['alsendo_connect_settings_general_shipping_method'] ) ? $template_data['options']['alsendo_connect_settings_general_shipping_method'] : '';
			if ( 0 === strpos( strtoupper( $pickup_method ), 'SELF_' ) ) {
				$pickup_method = 'self';
			} else {
				$pickup_method = 'courier'; // Uppercase will break request, API return error
			}

			$time = ! empty( $template_data['options']['alsendo_connect_settings_general_pickup_hour_to'] ) ? $template_data['options']['alsendo_connect_settings_general_pickup_hour_to'] : '';
		} else {
			$default_send_method = get_option( 'alsendo_connect_settings_general_shipping_method' );
			if ( 0 === strpos( strtoupper( $default_send_method ), 'SELF_' ) ) {
				$pickup_method = 'self';
				$pickup_date   = null;
				$time          = null;
			} else {
				$pickup_method = 'courier';
				$pickup_date   = $this->get_ecolet_default_pickup_date();
				$time          = get_option( 'alsendo_connect_settings_general_pickup_hour_to' );
			}
		}

		$data = array(
			'service'     => $ecolet->get_service_slug( $carrier_id ),
			'pickup'      => array(
				'type' => $pickup_method,
				'date' => $pickup_date,
				'time' => $time,
			),
			'contract_id' => null,
		);

		return $data;
	}


	/**
	 * Retrieves parcel specifications for Ecolet bulk shipment processing.
	 *
	 * Compiles parcel details including weight, dimensions (length, width, height),
	 * declared value, and content based on either main configuration settings or a
	 * specified package template. Supports automatic declared value calculation from
	 * order total. Handles custom text content or dynamic content generation based
	 * on order data.
	 *
	 * @param int    $order_id     The WooCommerce order ID.
	 * @param string $carrier_id   The carrier identifier.
	 * @param string $use_template The template identifier to use for parcel configuration, or 'alsendo-connect-main-config' for main settings.
	 *
	 * @return array Array of parcel data with weight, dimensions, declared value, and content, or empty array if order is invalid.
	 */
	public function ecolet_get_bulk_parcels( $order_id, $carrier_id, $use_template ) {

		$order = wc_get_order( $order_id );

		if ( ! $order || is_wp_error( $order ) ) {
			return array();
		}

		/*
		 * $parcels[] = array(
			'weight'         => (int) $parcel['package_weight'],
			'dimensions'     => array(
				'length' => (int) $parcel['package_length'],
				'width'  => (int) $parcel['package_width'],
				'height' => (int) $parcel['package_height'],
			),
			'declared_value' => (float) $parcel['declared_content'],
			'content'        => $parcel['package_contents'],
		);
		*/

		$ecolet_package_type = '';

		$package_templates_json = ( new Gateway_Settings_Templates_Helper() )->get_all_templates_json();
		$package_templates      = json_decode( $package_templates_json, true );

		if ( ! empty( $use_template ) && ! empty( $package_templates[ $use_template ] ) ) {
			$template_data = $package_templates[ $use_template ];

			$ecolet_package_type = ! empty( $template_data['options']['alsendo_connect_settings_general_parcel_type'] ) ? $template_data['options']['alsendo_connect_settings_general_parcel_type'] : '';

			$weight         = '';
			$length         = '';
			$width          = '';
			$height         = '';
			$declared_value = '';
			$content        = '';

			if ( 'envelope' === $ecolet_package_type ) {
				$weight = 1;
				$length = 15;
				$width  = 10;
				$height = 10;
			} else {
				$weight = ! empty( $template_data['options']['alsendo_connect_settings_general_package_weight'] ) ? $template_data['options']['alsendo_connect_settings_general_package_weight'] : '';
				$length = ! empty( $template_data['options']['alsendo_connect_settings_general_package_length'] ) ? $template_data['options']['alsendo_connect_settings_general_package_length'] : '';
				$width  = ! empty( $template_data['options']['alsendo_connect_settings_general_package_width'] ) ? $template_data['options']['alsendo_connect_settings_general_package_width'] : '';
				$height = ! empty( $template_data['options']['alsendo_connect_settings_general_package_height'] ) ? $template_data['options']['alsendo_connect_settings_general_package_height'] : '';

			}

			if ( 'yes' === $template_data['options']['alsendo_connect_settings_general_declared_content_auto'] ) {
				$declared_value = $order->get_total();
			} else {
				$declared_value = ! empty( $template_data['options']['alsendo_connect_settings_general_declared_content'] ) ? $template_data['options']['alsendo_connect_settings_general_declared_content'] : '';
			}

			$package_content_rule = $template_data['options']['alsendo_connect_settings_general_package_contents'];
			if ( ! empty( $package_content_rule ) ) {
				if ( 'custom_text' === $package_content_rule ) {
					$package_content = ! empty( $template_data['options']['alsendo_connect_settings_general_custom_text_content'] ) ? $template_data['options']['alsendo_connect_settings_general_custom_text_content'] : '';
				} else {
					$package_content = $this->get_parcel_content( $order_id, $package_content_rule );
				}
			}

			$data = array(
				'weight'         => (int) $weight,
				'dimensions'     => array(
					'length' => (int) $length,
					'width'  => (int) $width,
					'height' => (int) $height,
				),
				'declared_value' => $declared_value,
				'content'        => $package_content,
			);
		} else {
			$declared_value = get_option( 'alsendo_connect_settings_general_declared_content' );
			if ( 'yes' === get_option( 'alsendo_connect_settings_general_declared_content_auto' ) ) {
				$declared_value = $order->get_total();
			}

			$ecolet_package_type = get_option( 'alsendo_connect_settings_general_parcel_type' );

			$package_content      = '';
			$package_content_rule = get_option( 'alsendo_connect_settings_general_package_contents' );
			if ( ! empty( $package_content_rule ) ) {
				if ( 'custom_text' === $package_content_rule ) {
					$package_content = get_option( 'alsendo_connect_settings_general_custom_text_content' );
				} else {
					$package_content = $this->get_parcel_content( $order_id, $package_content_rule );
				}
			}

			$weight = (int) get_option( 'alsendo_connect_settings_general_package_weight', '' );
			$length = (int) get_option( 'alsendo_connect_settings_general_package_length', '' );
			$width  = (int) get_option( 'alsendo_connect_settings_general_package_width', '' );
			$height = (int) get_option( 'alsendo_connect_settings_general_package_height' );

			if ( 'envelope' === $ecolet_package_type ) {
				$weight = 1;
				$length = 15;
				$width  = 10;
				$height = 10;
			}

			$data = array(
				'weight'         => $weight,
				'dimensions'     => array(
					'length' => $length,
					'width'  => $width,
					'height' => $height,
				),
				'declared_value' => $declared_value,
				'content'        => $package_content,
			);
		}

		$parcels[] = $data;

		return $parcels;
	}



	/**
	 * Creates an Ecolet order for bulk shipment processing.
	 *
	 * Extracts order data, sends it to the Ecolet API, and processes the response.
	 * Updates order metadata with API response details including order ID, service slug,
	 * and AWB ID. Handles both successful order creation and error responses.
	 * Sends JSON response indicating success or failure with appropriate messages.
	 *
	 * @param int    $order_id     The WooCommerce order ID.
	 * @param string $carrier_id   The carrier identifier.
	 * @param string $use_template The template identifier to use for order configuration, or 'alsendo-connect-main-config' for main settings.
	 *
	 * @return void Outputs JSON response and terminates execution.
	 */
	public function ecolet_create_order_bulk( $order_id, $carrier_id, $use_template ) {

		$order = wc_get_order( $order_id );

		if ( ! $order || is_wp_error( $order ) ) {
			return array();
		}

		$order_to_api = $this->ecolet_extract_data_from_order( $order_id, $carrier_id, $use_template );

		unset( $order_to_api['receiver_woo_address'] );

		$ecolet = new Ecolet();
		$result = $ecolet->send_order( $order_to_api );

		//$result['error'] = 'TEST ECOLET';

		$did_retry_with_next_day_pickup = false;

		// If carrier rejects same-day pickup, optionally retry once with pickup date +1 day.
		if ( is_object( $result )
			&& property_exists( $result, 'status' )
			&& 'error' === $result->status
			&& 'yes' === get_option( 'alsendo_connect_settings_general_ecolet_day_to_send' )
			&& isset( $order_to_api['courier']['pickup']['date'] )
			&& is_string( $order_to_api['courier']['pickup']['date'] )
		) {
			$pickup_date_raw = trim( (string) $order_to_api['courier']['pickup']['date'] );
			if ( '' !== $pickup_date_raw ) {
				try {
					$dt = \DateTimeImmutable::createFromFormat( 'Y-m-d', $pickup_date_raw );
					if ( $dt instanceof \DateTimeImmutable ) {
						$order_to_api['courier']['pickup']['date'] = $this->get_next_business_day_from_ymd( $pickup_date_raw );
						$result                                    = $ecolet->send_order( $order_to_api );
						$did_retry_with_next_day_pickup            = true;
					}
				} catch ( \Throwable $e ) {
					// Ignore date parsing errors and keep original API response.
				}
			}
		}

		$res['ecolet_order'] = 1;
		$order_failed        = false;
		$meta                = array();

		if ( is_array( $result ) && ( ! empty( $result['exception'] ) || ! empty( $result['error'] ) || ! empty( $result['errors'] ) ) ) {
			$order_failed  = true;
			$res['status'] = 'error';

			if ( ! empty( $result['errors'] ) ) {
				if ( isset( $result['errors'] ) ) {
					$error_details  = $this->flatten_errors_to_string( $result['errors'] );
					$res['message'] = $error_details;
				}
			}
		}

		if ( is_object( $result ) && property_exists( $result, 'status' ) ) {
			if ( 'ordered' === $result->status ) {
				$res['message'] = esc_html__( 'Package created', 'alsendo-connect' );
				$res['status']  = 'ok';

				$meta['package_send'] = 1;
			}

			if ( 'error' === $result->status ) {
				$res['message']      = esc_html__( 'Error is occured', 'alsendo-connect' );
				$res['status']       = 'error';
				$res['ecolet_error'] = 1;
				$order_failed        = true;
				if ( property_exists( $result, 'api_error' ) ) {
					$res['message'] = $result->api_error;
				}
			}

			$meta['used_api']            = 'ecolet';
			$meta['alsendo_order']['id'] = property_exists( $result, 'id' ) ? $result->id : '';
			$res['uuid']                 = $meta['alsendo_order']['id'];

			if ( property_exists( $result, 'service' ) ) {
				$obj = $result->service;
				if ( is_object( $obj ) && property_exists( $obj, 'slug' ) ) {
					$meta['alsendo_order']['slug'] = $obj->slug;
				}
			}

			if ( ! empty( $res['uuid'] ) ) {
				$awb_id = $ecolet->get_awb_id( $res['uuid'] );
				if ( ! empty( $awb_id ) ) {
					$meta['alsendo_order']['ecolet_awb_id'] = $awb_id;
					$res['awb_id']                          = $awb_id;
				}
			}

			if ( empty( $meta['receiver'] ) ) {
				$meta['receiver']                               = ! empty( $order_to_api['receiver'] ) ? $order_to_api['receiver'] : '';
				$meta['receiver']['city']                       = ! empty( $order_to_api['receiver']['locality'] ) ? $order_to_api['receiver']['locality'] : '';
				$meta['package_properties']['pickup_date']      = ! empty( $order_to_api['courier']['pickup']['date'] ) ? $order_to_api['courier']['pickup']['date'] : '';
				$meta['package_properties']['declared_content'] = ! empty( $order_to_api['parccels'][0]['content'] ) ? $order_to_api['parccels'][0]['content'] : '';
			}

			$order->update_meta_data( 'alsendo_connect_wc_order', $meta );
			$order->save();

			if ( 'ok' === $res['status'] ) {
				if ( 'yes' === get_option( 'alsendo_connect_settings_general_set_order_status_completed' ) ) {
					$current_order_status = $order->get_status();
					if ( 'completed' !== $current_order_status ) {
						$order->update_status( 'wc-completed' );
					}
				}
			}
		}

		if ( $order_failed ) {
			wp_send_json_error( $res );
		} else {
			wp_send_json_success( $res );
		}
	}



	/**
	 * Flattens a multi-dimensional error array into a single string.
	 *
	 * Recursively walks through the array and extracts all string values,
	 * then concatenates them into a space-separated string. Useful for
	 * converting nested API error responses into readable error messages.
	 *
	 * @param array $data_array The multi-dimensional array containing error data.
	 *
	 * @return string Space-separated string of all error messages.
	 */
	public function flatten_errors_to_string( $data_array ) {
		$result = array();

		array_walk_recursive(
			$data_array,
			function ( $value ) use ( &$result ) {
				if ( is_string( $value ) ) {
					$result[] = $value;
				}
			}
		);

		return implode( ' ', $result );
	}



	/**
	 * Retrieves the linked carrier ID for an order's shipping method.
	 *
	 * Extracts the carrier ID associated with the order's shipping method by checking
	 * the shipping method settings. If not found in direct settings, attempts to retrieve
	 * the carrier ID through flexible shipping integration. Returns empty string if order
	 * is invalid or carrier ID is non-numeric.
	 *
	 * @param int $order_id The WooCommerce order ID.
	 *
	 * @return string The linked carrier ID if found and numeric, empty string otherwise.
	 */
	public function get_linked_carrier_id( $order_id ) {

		$alsendo_api_carrier_id = '';

		$order = wc_get_order( $order_id );

		if ( ! $order || is_wp_error( $order ) ) {
			return $alsendo_api_carrier_id;
		}

		$shipping_method_instance_id = '';
		$shipping_id                 = '';

		foreach ( $order->get_shipping_methods() as $shipping_method ) {
			$shipping_method_instance_id = $shipping_method->get_instance_id();
			$shipping_id                 = $shipping_method->get_method_id();
		}

		$shipping_method_settings_name = 'woocommerce_' . $shipping_id . '_' . $shipping_method_instance_id . '_settings';
		$shipping_method_settings      = get_option( $shipping_method_settings_name );
		if ( ! empty( $shipping_method_settings['alsendo_connect_linked_api_shipping_method'] ) ) {
			$alsendo_api_carrier_id = $shipping_method_settings['alsendo_connect_linked_api_shipping_method'];
		}

		if ( empty( $alsendo_api_carrier_id ) ) {
			$alsendo_api_carrier_id = alsendo_connect()->get_carrier_id_linked_to_flexible_shipping( $shipping_method_instance_id );
		}

		return is_numeric( $alsendo_api_carrier_id ) ? $alsendo_api_carrier_id : '';
	}




	/**
	 * Creates an Apaczka order for bulk shipment processing.
	 *
	 * Extracts order data, sends it to the Apaczka API, and processes the response.
	 * Logs request and response data for debugging. Updates order metadata with API
	 * response details including order ID, service information, waybill number, and
	 * tracking URL. Handles both successful order creation and error responses.
	 * Sends JSON response indicating success or failure with appropriate messages.
	 *
	 * @param int    $order_id     The WooCommerce order ID.
	 * @param string $carrier_id   The carrier identifier.
	 * @param string $use_template The template identifier to use for order configuration, or 'alsendo-connect-main-config' for main settings.
	 *
	 * @return void Outputs JSON response and terminates execution.
	 */
	public function apaczka_create_order_bulk( $order_id, $carrier_id, $use_template ) {

		$order = wc_get_order( $order_id );

		if ( ! $order || is_wp_error( $order ) ) {
			return array();
		}

		$order_to_api = $this->apaczka_extract_data_from_order( $order_id, $carrier_id, $use_template );

		if ( function_exists( 'wc_get_logger' ) ) {
			$logger = wc_get_logger();
			$logger->log(
				'debug',
				'BULK ORDER CREATION, REQUEST: ',
				array(
					'source'       => 'alsendo-connect-order-' . $order_id,
					'debug_place'  => __METHOD__ . ': ' . __LINE__,
					'order_id'     => $order_id,
					'create_order' => $order_to_api,
				)
			);
		}

		// create ORDER in API.
		$result = ( new Alsendo_API() )->order_send( $order_to_api );

		//$result['error'] = 'TEST APACZKA';

		if ( function_exists( 'wc_get_logger' ) ) {
			$logger = wc_get_logger();
			$logger->log(
				'debug',
				'BULK ORDER CREATION, RESPONSE: ',
				array(
					'source'       => 'alsendo-connect-order-' . $order_id,
					'debug_place'  => __METHOD__ . ': ' . __LINE__,
					'order_id'     => $order_id,
					'api_response' => $result,
				)
			);
		}

		$res['apaczka_order'] = 1;
		$order_failed         = false;
		$meta                 = array();

		if ( is_array( $result ) ) {
			if ( ! empty( $result['exception'] ) || ! empty( $result['error'] ) ) {
				if ( ! empty( $result['exception'] ) ) {
					$error_details = $result['exception'];
				} elseif ( ! empty( $result['error'] ) ) {
					$error_details = $result['error'];
				}

				$res['message'] = $error_details;
				$res['status']  = 'error';
				$order_failed   = true;
			}
		}

		if ( is_object( $result ) && property_exists( $result, 'status' ) && property_exists( $result, 'id' ) ) {

			if ( ! empty( $result->status ) ) {
				$meta['package_send'] = 1;

				$res['error_messages'] = '';
				$res['message']        = esc_html__( 'Package created', 'alsendo-connect' );
				$res['status']         = 'ok';
				$res['apaczka_ok']     = 1;
				$res['uuid']           = $result->id;
				$res['awb']            = property_exists( $result, 'waybill_number' ) ? $result->waybill_number : '';
				$res['service_name']   = property_exists( $result, 'service_name' ) ? $result->service_name : '';
				$res['tracking_url']   = property_exists( $result, 'tracking_url' ) ? $result->tracking_url : '';
			}

			$meta['used_api']                        = 'apaczka';
			$meta['alsendo_order']['id']             = $result->id;
			$meta['alsendo_order']['service_id']     = property_exists( $result, 'service_id' ) ? $result->service_id : '';
			$meta['alsendo_order']['service_name']   = property_exists( $result, 'service_name' ) ? $result->service_name : '';
			$meta['alsendo_order']['waybill_number'] = property_exists( $result, 'waybill_number' ) ? $result->waybill_number : '';
			$meta['alsendo_order']['tracking_url']   = property_exists( $result, 'tracking_url' ) ? $result->tracking_url : '';

			if ( empty( $meta['package_properties']['title'] ) ) {
				$meta['package_properties']['title'] = ! empty( $order_to_api['package_properties']['title'] ) ? $order_to_api['package_properties']['title'] : '';
			}
			if ( empty( $meta['package_properties']['cod'] ) ) {
				$meta['package_properties']['cod'] = ! empty( $order_to_api['package_properties']['cod'] ) ? $order_to_api['package_properties']['cod'] : '';
			}
			if ( empty( $meta['receiver'] ) ) {
				$meta['receiver'] = ! empty( $order_to_api['address']['receiver'] ) ? $order_to_api['address']['receiver'] : '';
			}

			$order->update_meta_data( 'alsendo_connect_wc_order', $meta );
			$order->save();

			if ( 'ok' === $res['status'] ) {
				if ( 'yes' === get_option( 'alsendo_connect_settings_general_set_order_status_completed' ) ) {
					$current_order_status = $order->get_status();
					if ( 'completed' !== $current_order_status ) {
						$order->update_status( 'wc-completed' );
					}
				}
			}
		}

		if ( $order_failed ) {
			wp_send_json_error( $res );
		} else {
			wp_send_json_success( $res );
		}
	}



	/**
	 * Extracts and compiles shipment data from a WooCommerce order for Apaczka processing.
	 *
	 * Retrieves comprehensive shipping information including sender and receiver details,
	 * parcel specifications, pickup data, notification preferences, and additional options.
	 * Supports both main configuration and template-based settings. Handles dispatch point
	 * selection for self-pickup methods based on carrier. Converts parcel types to
	 * Apaczka-specific codes (PACZKA, PALETA, etc.). Formats dimensions, weight, and
	 * shipment value according to API requirements.
	 *
	 * @param int    $order_id     The WooCommerce order ID.
	 * @param string $carrier_id   The carrier identifier.
	 * @param string $use_template The template identifier to use for data extraction, or 'alsendo-connect-main-config' for main settings.
	 *
	 * @return array Associative array containing complete Apaczka order data including service ID, addresses, options, notifications, and shipment details, or empty array if order is invalid.
	 */
	public function apaczka_extract_data_from_order( $order_id, $carrier_id, $use_template ) {
		$order = wc_get_order( $order_id );

		if ( ! $order || is_wp_error( $order ) ) {
			return array();
		}

		$alsendo_api_carrier_id = $this->get_linked_carrier_id( $order_id );
		if ( ! empty( $alsendo_api_carrier_id ) ) {
			$service_id = $alsendo_api_carrier_id;
		}

		$sender_details            = $this->apaczka_get_bulk_sender_details( $use_template );
		$bank_account              = ! empty( $sender_details['bank_account_number'] ) ? $sender_details['bank_account_number'] : '';
		$sender_foreign_address_id = ! empty( $sender_details['foreign_address_id'] ) ? $sender_details['foreign_address_id'] : '';

		$pickup_date = gmdate( 'Y-m-d' );

		$package_templates_json = ( new Gateway_Settings_Templates_Helper() )->get_all_templates_json();
		$package_templates      = json_decode( $package_templates_json, true );

		$cod_amount     = 0;
		$payment_method = $order->get_payment_method();
		if ( 'cod' === $payment_method ) {
			$cod_amount = $order->get_total();
			$cod_amount = $cod_amount * 100;
		}

		if ( ! empty( $use_template ) && ! empty( $package_templates[ $use_template ] ) ) {

			$template_root      = $package_templates[ $use_template ];
			$additional_parcels = ! empty( $template_root['additional_parcels'] ) && is_array( $template_root['additional_parcels'] )
				? $template_root['additional_parcels']
				: array();

			$template_data   = $template_root;
			$shipment_value  = 0;
			$pickup_data     = array();
			$shipment        = array();
			$shipments       = array();
			$package_content = '';

			if ( ! empty( $template_data['options'] ) ) {
				$template_data = $template_data['options'];
			}

			$get_shipment_type_code = static function ( string $parcel_type ): string {
				$shipment_type_code = 'PACZKA';
				if ( 'palette_60x80' === $parcel_type ) {
					$shipment_type_code = 'POLPALETA';
				}
				if ( 'europalette' === $parcel_type ) {
					$shipment_type_code = 'PALETA';
				}
				if ( 'palette_120x100' === $parcel_type ) {
					$shipment_type_code = 'PALETA_PRZEMYSLOWA';
				}
				if ( 'palette_120x120' === $parcel_type ) {
					$shipment_type_code = 'PALETA_PRZEMYSLOWA_B';
				}

				return $shipment_type_code;
			};

			$pickup_method = ! empty( $template_data['alsendo_connect_settings_general_shipping_method'] ) ? $template_data['alsendo_connect_settings_general_shipping_method'] : '';
			if ( 'SELF' === $pickup_method || 'POINT' === $pickup_method ) {
				$carrier = alsendo_connect()->get_logo_apaczka( $service_id );
				if ( 'inpost' === $carrier ) {
					$sender_foreign_address_id = ! empty( $template_data['alsendo_connect_settings_general_dispath_point_inpost'] ) ? $template_data['alsendo_connect_settings_general_dispath_point_inpost'] : '';
				}
				if ( 'pocztex' === $carrier ) {
					$sender_foreign_address_id = ! empty( $template_data['alsendo_connect_settings_general_dispath_point_kurier48'] ) ? $template_data['alsendo_connect_settings_general_dispath_point_kurier48'] : '';
				}
				if ( 'ups' === $carrier ) {
					$sender_foreign_address_id = ! empty( $template_data['alsendo_connect_settings_general_dispath_point_ups'] ) ? $template_data['alsendo_connect_settings_general_dispath_point_ups'] : '';
				}
				if ( 'dpd' === $carrier ) {
					$sender_foreign_address_id = ! empty( $template_data['alsendo_connect_settings_general_dispath_point_dpd'] ) ? $template_data['alsendo_connect_settings_general_dispath_point_dpd'] : '';
				}
			}

			$package_content_rule = ! empty( $template_data['alsendo_connect_settings_general_package_contents'] ) ? $template_data['alsendo_connect_settings_general_package_contents'] : '';
			if ( ! empty( $package_content_rule ) ) {
				if ( 'custom_text' === $package_content_rule ) {
					$package_content = ! empty( $template_data['alsendo_connect_settings_general_custom_text_content'] ) ? $template_data['alsendo_connect_settings_general_custom_text_content'] : '';
				} else {
					$package_content = $this->get_parcel_content( $order_id, $package_content_rule );
				}
			}

			$type_code_from_settings = ! empty( $template_data['alsendo_connect_settings_general_parcel_type'] ) ? $template_data['alsendo_connect_settings_general_parcel_type'] : 'PACZKA';
			$shipment_type_code      = $get_shipment_type_code( (string) $type_code_from_settings );

			$lenght  = ! empty( $template_data['alsendo_connect_settings_general_package_length'] ) ? $template_data['alsendo_connect_settings_general_package_length'] : 0;
			$width   = ! empty( $template_data['alsendo_connect_settings_general_package_width'] ) ? $template_data['alsendo_connect_settings_general_package_width'] : 0;
			$height  = ! empty( $template_data['alsendo_connect_settings_general_package_height'] ) ? $template_data['alsendo_connect_settings_general_package_height'] : 0;
			$weight  = ! empty( $template_data['alsendo_connect_settings_general_package_weight'] ) ? $template_data['alsendo_connect_settings_general_package_weight'] : 0;
			$is_nstd = ! empty( $template_data['alsendo_connect_settings_general_is_nstd'] ) && 'yes' === $template_data['alsendo_connect_settings_general_is_nstd'] ? 1 : 0;

			$shipment = array(
				'dimension1'         => (int) $lenght,
				'dimension2'         => (int) $width,
				'dimension3'         => (int) $height,
				'weight'             => (int) $weight,
				'is_nstd'            => $is_nstd,
				'shipment_type_code' => $shipment_type_code,
			);

			$shipments[] = $shipment;

			if ( ! empty( $additional_parcels ) ) {
				foreach ( array_slice( $additional_parcels, 0, 9 ) as $parcel ) {
					if ( ! is_array( $parcel ) ) {
						continue;
					}

					$parcel_type = ! empty( $parcel['parcel_type'] ) ? (string) $parcel['parcel_type'] : '';
					$shipments[] = array(
						'dimension1'         => (int) ( $parcel['package_length'] ?? 0 ),
						'dimension2'         => (int) ( $parcel['package_width'] ?? 0 ),
						'dimension3'         => (int) ( $parcel['package_height'] ?? 0 ),
						'weight'             => (int) ( $parcel['package_weight'] ?? 0 ),
						'is_nstd'            => ! empty( $parcel['is_nstd'] ) && 'yes' === $parcel['is_nstd'] ? 1 : 0,
						'shipment_type_code' => $get_shipment_type_code( $parcel_type ),
					);
				}
			}

			$shipment_value = ! empty( $template_data['alsendo_connect_settings_general_declared_content'] ) ? floatval( $template_data['alsendo_connect_settings_general_declared_content'] ) : 0;
			if ( 'yes' === get_option( 'alsendo_connect_settings_general_declared_content_auto' ) ) {
				$shipment_value = $order->get_total();
			}

			$hour_from = ! empty( $template_data['alsendo_connect_settings_general_pickup_hour_from'] ) ? $template_data['alsendo_connect_settings_general_pickup_hour_from'] : '9:00';
			$hour_to   = ! empty( $template_data['alsendo_connect_settings_general_pickup_hour_to'] ) ? $template_data['alsendo_connect_settings_general_pickup_hour_to'] : '19:00';

			$pickup_data = array(
				'type'       => $pickup_method,
				// endpoint: service_structure
				'date'       => $pickup_date,
				// Y-m-d
				'hours_from' => gmdate( 'H:i', strtotime( $hour_from ) ),
				// H:i - pickup_hours
				'hours_to'   => gmdate( 'H:i', strtotime( $hour_to ) ),
				// H:i - pickup_hours
			);

		} else {

			$pickup_method = get_option( 'alsendo_connect_settings_general_shipping_method' );
			if ( 'SELF' === $pickup_method || 'POINT' === $pickup_method ) {
				$carrier = alsendo_connect()->get_logo_apaczka( $service_id );
				if ( 'inpost' === $carrier ) {
					$sender_foreign_address_id = get_option( 'alsendo_connect_settings_general_dispath_point_inpost' );
				}
				if ( 'pocztex' === $carrier ) {
					$sender_foreign_address_id = get_option( 'alsendo_connect_settings_general_dispath_point_kurier48' );
				}
				if ( 'ups' === $carrier ) {
					$sender_foreign_address_id = get_option( 'alsendo_connect_settings_general_dispath_point_ups' );
				}
				if ( 'dpd' === $carrier ) {
					$sender_foreign_address_id = get_option( 'alsendo_connect_settings_general_dispath_point_dpd' );
				}
			}

			$shipment_value = floatval( get_option( 'alsendo_connect_settings_general_declared_content' ) );
			if ( 'yes' === get_option( 'alsendo_connect_settings_general_declared_content_auto' ) ) {
				$shipment_value = $order->get_total();
			}

			$package_content      = '';
			$package_content_rule = get_option( 'alsendo_connect_settings_general_package_contents' );
			if ( ! empty( $package_content_rule ) ) {
				if ( 'custom_text' === $package_content_rule ) {
					$package_content = get_option( 'alsendo_connect_settings_general_custom_text_content' );
				} else {
					$package_content = $this->get_parcel_content( $order_id, $package_content_rule );
				}
			}

			$shipment_type_code      = 'PACZKA';
			$type_code_from_settings = get_option( 'alsendo_connect_settings_general_parcel_type' );

			if ( 'palette_60x80' === $type_code_from_settings ) {
				$shipment_type_code = 'POLPALETA';
			}

			if ( 'europalette' === $type_code_from_settings ) {
				$shipment_type_code = 'PALETA';
			}

			if ( 'palette_120x100' === $type_code_from_settings ) {
				$shipment_type_code = 'PALETA_PRZEMYSLOWA';
			}

			if ( 'palette_120x120' === $type_code_from_settings ) {
				$shipment_type_code = 'PALETA_PRZEMYSLOWA_B';
			}

			$shipment = array(
				'dimension1'         => (int) get_option( 'alsendo_connect_settings_general_package_length' ),
				'dimension2'         => (int) get_option( 'alsendo_connect_settings_general_package_width' ),
				'dimension3'         => (int) get_option( 'alsendo_connect_settings_general_package_height' ),
				'weight'             => (int) get_option( 'alsendo_connect_settings_general_package_weight' ),
				'is_nstd'            => get_option( 'alsendo_connect_settings_general_is_nstd' ) === 'yes' ? 1 : 0,
				'shipment_type_code' => $shipment_type_code,
			);

			$pickup_data = array(
				'type'       => $pickup_method,
				// endpoint: service_structure
				'date'       => $pickup_date,
				// Y-m-d
				'hours_from' => gmdate( 'H:i', strtotime( get_option( 'alsendo_connect_settings_general_pickup_hour_from' ) ) ),
				// H:i - pickup_hours
				'hours_to'   => gmdate( 'H:i', strtotime( get_option( 'alsendo_connect_settings_general_pickup_hour_to' ) ) ),
				// H:i - pickup_hours
			);
		}

		$apaczka_order = array(
			'woo_order_id'   => $order_id,
			'service_id'     => $service_id,
			'address'        => array(
				'sender'   => array(
					'country_code'       => ! empty( $sender_details['country_code'] ) ? strtoupper( $sender_details['country_code'] ) : '',
					// Kod ISO 3166.
					'name'               => ! empty( $sender_details['name'] ) ? $sender_details['name'] : '',
					'line1'              => ! empty( $sender_details['line1'] ) ? $sender_details['line1'] : '',
					'line2'              => '',
					'postal_code'        => ! empty( $sender_details['postal_code'] ) ? $sender_details['postal_code'] : '',
					'city'               => ! empty( $sender_details['city'] ) ? $sender_details['city'] : '',
					'is_residential'     => isset( $sender_details['is_residential'] ) ? $sender_details['is_residential'] : '',
					// 0 / 1
					'contact_person'     => ! empty( $sender_details['contact_person'] ) ? $sender_details['contact_person'] : '',
					'email'              => ! empty( $sender_details['email'] ) ? $sender_details['email'] : '',
					'phone'              => ! empty( $sender_details['phone'] ) ? $sender_details['phone'] : '',
					'foreign_address_id' => $sender_foreign_address_id,
				),
				'receiver' => $this->apaczka_get_bulk_receiver_details( $order_id, $carrier_id ),
			),
			'option'         => array(
				/*
				'31'  => 0, // powiadomienie sms,
				'11 ' => 0, // rod
				'19'  => 0, // dostawa w sobotę,
				'25'  => 0, // dostawa w godzinach,
				'58'  => 0,*/  // ostrożnie
			),
			'notification'   => array(
				'new'       => array(  // Powiadomienia o utworzeniu przesyłki>
					'isReceiverEmail' => null, // 0 / 1
					'isReceiverSms'   => null, // 0 / 1
					'isSenderEmail'   => null, // 0 / 1
				),
				'sent'      => array(  // Powiadomienia o wysłaniu przesyłki
					'isReceiverEmail' => null, // 0 / 1
					'isReceiverSms'   => null, // 0 / 1
					'isSenderEmail'   => null, // 0 / 1
				),
				'exception' => array( // Powiadomienia o wyjątku
					'isReceiverEmail' => null, // 0 / 1
					'isReceiverSms'   => null, // 0 / 1
					'isSenderEmail'   => null, // 0 / 1
				),
				'delivered' => array(  // Powiadomienia o doręczeniu
					'isReceiverEmail' => null, // 0 / 1
					'isReceiverSms'   => null, // 0 / 1
					'isSenderEmail'   => null, // 0 / 1
				),
			),
			// 'shipment_value' => (int) ( ( (float) $data['package_properties']['declared_content'] ) * 100 ),
			'shipment_value' => $shipment_value,

			'cod'            => array(
				'amount'      => $cod_amount,  // // wartość w groszach
				'bankaccount' => $bank_account,
			),

			'pickup'         => $pickup_data,
			'shipment'       => ! empty( $shipments ) ? $shipments : array( $shipment ),
			'comment'        => '',
			'content'        => $package_content,
			'is_zebra'       => null,
			// 0 / 1 (wartość opcjonalna, w przypadku nie podania etykieta będzie zgodna z ustawieniami konta).
		);

		return $apaczka_order;
	}

	/**
	 * Retrieves sender details for Apaczka bulk shipment processing.
	 *
	 * Uses default sender template values when available (except for main-config mode),
	 * and falls back to global sender settings for any missing fields.
	 *
	 * @param string $use_template The package template identifier used for bulk creation.
	 *
	 * @return array Associative array with sender fields used by Apaczka payload.
	 */
	public function apaczka_get_bulk_sender_details( $use_template ) {
		$sender_template_values = array();
		if ( 'alsendo-connect-main-config' !== $use_template ) {
			$selected_sender_template = get_option( 'alsendo_connect_settings_general_select_sender_template', '' );
			if ( ! empty( $selected_sender_template ) ) {
				$sender_templates_json = ( new Sender_Settings_Templates_Helper() )->get_all_templates_json();
				$sender_templates      = json_decode( $sender_templates_json, true );
				if ( ! empty( $sender_templates[ $selected_sender_template ]['options'] ) && is_array( $sender_templates[ $selected_sender_template ]['options'] ) ) {
					$sender_template_values = $sender_templates[ $selected_sender_template ]['options'];
				}
			}
		}

		$get_sender_value = static function ( string $key, $default = '' ) use ( $sender_template_values ) {
			$option_key = 'alsendo_connect_settings_general_sender_' . $key;
			if ( isset( $sender_template_values[ $option_key ] ) && '' !== $sender_template_values[ $option_key ] ) {
				return $sender_template_values[ $option_key ];
			}

			return get_option( $option_key, $default );
		};

		$sender_name = $get_sender_value( 'company_name' );
		if ( empty( $sender_name ) ) {
			$sender_name = trim( $get_sender_value( 'first_name' ) . ' ' . $get_sender_value( 'last_name' ) );
		}

		$flat = $get_sender_value( 'apartment_number', '' );

		$line_1 = trim( $get_sender_value( 'street', '' ) . ' ' . $get_sender_value( 'building_number', '' ) );
		if ( ! empty( $flat ) ) {
			$line_1 .= '/' . $flat;
		}

		return array(
			'country_code'        => $get_sender_value( 'country', get_option( ( new Global_Settings() )->get_setting_id( 'sender_country' ) ) ),
			'name'                => $sender_name,
			'line1'               => $line_1,
			'postal_code'         => $get_sender_value( 'postal_code', '' ),
			'city'                => $get_sender_value( 'city', '' ),
			'is_residential'      => $get_sender_value( 'is_residential' ),
			'contact_person'      => $get_sender_value( 'contact_person' ),
			'email'               => $get_sender_value( 'email' ),
			'phone'               => $get_sender_value( 'phone' ),
			'bank_account_number' => $get_sender_value( 'bank_account_number', '' ),
			'foreign_address_id'  => '',
		);
	}

	/**
	 * Retrieves receiver details for Apaczka bulk shipment processing from order data.
	 *
	 * Extracts and compiles receiver information from WooCommerce order, prioritizing
	 * shipping address over billing address for most fields. Combines address line 1 and
	 * line 2 into a single comma-separated string. Formats phone number by removing spaces.
	 * Determines residential status based on company name presence. Includes foreign
	 * address ID if delivery point data is available.
	 *
	 * @param int    $order_id   The WooCommerce order ID.
	 * @param string $carrier_id The carrier identifier.
	 *
	 * @return array Associative array containing complete receiver details including address, contact info, residential status, and optional foreign address ID, or empty array if order is invalid.
	 */
	public function apaczka_get_bulk_receiver_details( $order_id, $carrier_id ) {

		$order = wc_get_order( $order_id );

		if ( ! $order || is_wp_error( $order ) ) {
			return array();
		}

		$receiver_country = '';
		if ( ! empty( $order->get_shipping_country() ) ) {
			$receiver_country = $order->get_shipping_country();
		} elseif ( ! empty( $order->get_billing_country() ) ) {
			$receiver_country = $order->get_billing_country();
		}

		$shipping_name    = $order->get_shipping_company();
		$shipping_contact = '';
		if ( empty( $shipping_name ) ) {
			$shipping_name    = $order->get_shipping_first_name() . ' '
								. $order->get_shipping_last_name();
			$shipping_contact = $order->get_shipping_first_name() . ' '
								. $order->get_shipping_last_name();

		} else {
			$shipping_contact = $order->get_shipping_first_name() . ' '
								. $order->get_shipping_last_name();
		}

		$receiver_name = '';
		if ( ! empty( $order->get_billing_company() ) ) {
			$receiver_name = $order->get_billing_company();
		} elseif ( ! empty( $order->get_shipping_company() ) ) {
			$receiver_name = $order->get_shipping_company();
		} else {
			$receiver_name = $shipping_contact;
		}

		$receiver_street = '';
		if ( ! empty( $order->get_shipping_address_1() ) ) {
			$receiver_street = $order->get_shipping_address_1();
		} elseif ( ! empty( $order->get_billing_address_1() ) ) {
			$receiver_street = $order->get_billing_address_1();
		}

		$line_2 = '';
		if ( ! empty( $order->get_shipping_address_2() ) ) {
			$line_2 = $order->get_shipping_address_2();
		} elseif ( ! empty( $order->get_billing_address_2() ) ) {
			$line_2 = $order->get_billing_address_2();
		}

		$full_line_1 = $receiver_street . ', ' . $line_2;

		$receiver_postal_code = '';
		if ( ! empty( $order->get_shipping_postcode() ) ) {
			$receiver_postal_code = $order->get_shipping_postcode();
		} elseif ( ! empty( $order->get_billing_postcode() ) ) {
			$receiver_postal_code = $order->get_billing_postcode();
		}

		$receiver_city = '';
		if ( ! empty( $order->get_shipping_city() ) ) {
			$receiver_city = $order->get_shipping_city();
		} elseif ( ! empty( $order->get_billing_city() ) ) {
			$receiver_city = $order->get_billing_city();
		}

		$receiver_email = '';
		if ( ! empty( $order->get_billing_email() ) ) {
			$receiver_email = $order->get_billing_email();
		}

		$receiver_phone = '';
		if ( ! empty( $order->get_shipping_phone() ) ) {
			$receiver_phone = $order->get_shipping_phone();
		} elseif ( ! empty( $order->get_billing_phone() ) ) {
			$receiver_phone = $order->get_billing_phone();
		}

		$receiver_phone = str_replace( ' ', '', $receiver_phone );
		$receiver_phone = trim( $receiver_phone );

		$receiver_company = null;
		if ( ! empty( $order->get_shipping_company() ) ) {
			$receiver_company = $order->get_shipping_company();
		} elseif ( ! empty( $order->get_billing_company() ) ) {
			$receiver_company = $order->get_billing_company();
		}

		$receiver_is_residential = '1';
		if ( ! empty( $receiver_company ) ) {
			$receiver_is_residential = '0';
		}

		$receiver = array(
			'country_code'       => strtoupper( $receiver_country ),
			'name'               => $receiver_name,
			'line1'              => $full_line_1,
			'line2'              => '',
			'postal_code'        => $receiver_postal_code,
			'city'               => $receiver_city,
			'contact_person'     => $shipping_contact,
			'phone'              => $receiver_phone,
			'email'              => $receiver_email,
			'is_residential'     => $receiver_is_residential,
			'foreign_address_id' => '',
		);

		$delivery_point_data = $this->get_woo_order_meta( $order_id, 'alsendo_connect_delivery_point' );
		if ( ! empty( $delivery_point_data['apm_foreign_access_point_id'] ) ) {
			$receiver['foreign_address_id'] = $delivery_point_data['apm_foreign_access_point_id'];
		}

		return $receiver;
	}


	/**
	 * Determines if valuation should be skipped for an order's shipping method.
	 *
	 * Checks the shipping method settings to see if the skip valuation option is enabled.
	 * Returns true if the setting is set to 'yes', false otherwise or if order is invalid.
	 *
	 * @param int $order_id The WooCommerce order ID.
	 *
	 * @return bool True if valuation should be skipped, false otherwise.
	 */
	public function is_skip_valuation( $order_id ) {
		$skip_valuation              = false;
		$shipping_method_id          = '';
		$shipping_method_instance_id = '';

		$order = wc_get_order( $order_id );

		if ( ! $order || is_wp_error( $order ) ) {
			return $skip_valuation;
		}

		foreach ( $order->get_shipping_methods() as $shipping_method ) {
			$shipping_method_instance_id = $shipping_method->get_instance_id();
			$shipping_method_id          = $shipping_method->get_method_id();
		}

		$shipping_method_settings_name = 'woocommerce_' . $shipping_method_id . '_' . $shipping_method_instance_id . '_settings';
		$shipping_method_settings      = get_option( $shipping_method_settings_name );

		if ( ! empty( $shipping_method_settings['alsendo_connect_skip_valuation'] ) && 'yes' === $shipping_method_settings['alsendo_connect_skip_valuation'] ) {
			$skip_valuation = true;
		}

		return $skip_valuation;
	}



	/**
	 * Generates an HTML select dropdown for package template selection.
	 *
	 * Creates a select element populated with available package templates from settings.
	 * If no templates are defined, falls back to main configuration option with a
	 * translated label based on the default shipping method (courier, point, or self-pickup).
	 * Marks the currently selected template as selected in the dropdown.
	 *
	 * @return string HTML select element containing package template options.
	 */
	public function get_package_template_selector() {

		$selected_package_template = get_option( 'alsendo_connect_settings_general_select_package_template' );
		$package_templates_json    = ( new Gateway_Settings_Templates_Helper() )->get_all_templates_json();
		$package_templates         = json_decode( $package_templates_json, true );

		$selector = '<select id="alsendo-connect-bulk-template-select" class="alsendo-connect-bulk-template">';

		if ( ! empty( $package_templates ) && is_array( $package_templates ) ) {
			foreach ( $package_templates as $key => $template ) {
				if ( $selected_package_template === $key ) {
					$selector .= '<option value="' . esc_attr( $key ) . '" selected>' . esc_html( $template['name'] ) . '</option>';
				} else {
					$selector .= '<option value="' . esc_attr( $key ) . '">' . esc_html( $template['name'] ) . '</option>';
				}
			}
		} else {
			$key         = 'alsendo-connect-main-config';
			$option_name = '';
			$send_method = get_option( 'alsendo_connect_settings_general_shipping_method' );

			if ( 'COURIER' === strtoupper( $send_method ) ) {
				$option_name = esc_html__( 'Courier pickup request', 'alsendo-connect' );
			}

			if ( 'POINT' === strtoupper( $send_method ) ) {
				$option_name = esc_html__( 'Shipment directly at the point', 'alsendo-connect' );
			}

			if ( 'SELF' === strtoupper( $send_method ) || 0 === strpos( strtoupper( $send_method ), 'SELF_' ) ) {
				$option_name = esc_html__( 'Pickup self', 'alsendo-connect' );
			}

			$selector .= '<option value="' . esc_attr( $key ) . '">' . esc_html( $option_name ) . '</option>';
		}

		$selector .= '</select>';

		return $selector;
	}



	/**
	 * Retrieves and formats package template data for display.
	 *
	 * Compiles human-readable package details including template name, shipping method,
	 * parcel type, and dimensions (length x width x height x weight) from either the
	 * selected package template or main configuration settings. Returns formatted HTML
	 * string with line breaks for display purposes.
	 *
	 * @return string Formatted HTML string containing package template details including shipping method, parcel type, and dimensions.
	 */
	public function get_package_template_data() {
		$selected_package_template = get_option( 'alsendo_connect_settings_general_select_package_template' );
		$package_templates_json    = ( new Gateway_Settings_Templates_Helper() )->get_all_templates_json();
		$package_templates         = json_decode( $package_templates_json, true );

		$package_details = '';
		$template_name   = '';
		$send_method     = '';
		$parcel_type     = '';
		$length          = '';
		$width           = '';
		$height          = '';
		$weight          = '';

		if ( ! empty( $selected_package_template ) && ! empty( $package_templates[ $selected_package_template ] ) ) {

			$data = $package_templates[ $selected_package_template ];

			if ( ! empty( $data['name'] ) ) {
				$template_name = $data['name'];
			}

			if ( ! empty( $data['options']['alsendo_connect_settings_general_shipping_method'] ) ) {
				$send_method = $this->get_template_send_method( $data['options']['alsendo_connect_settings_general_shipping_method'] );
			}

			if ( ! empty( $data['options']['alsendo_connect_settings_general_parcel_type'] ) ) {
				$parcel_type = $this->get_parcel_type( $data['options']['alsendo_connect_settings_general_parcel_type'] );
			}

			if ( ! empty( $data['options']['alsendo_connect_settings_general_package_length'] ) ) {
				$length = $data['options']['alsendo_connect_settings_general_package_length'];
			}

			if ( ! empty( $data['options']['alsendo_connect_settings_general_package_width'] ) ) {
				$width = $data['options']['alsendo_connect_settings_general_package_width'];
			}

			if ( ! empty( $data['options']['alsendo_connect_settings_general_package_height'] ) ) {
				$height = $data['options']['alsendo_connect_settings_general_package_height'];
			}

			if ( ! empty( $data['options']['alsendo_connect_settings_general_package_weight'] ) ) {
				$weight = $data['options']['alsendo_connect_settings_general_package_weight'];
			}

			$package_details  = '<br>' . esc_html__( 'Template', 'alsendo-connect' ) . ': ' . $template_name . '<br>';
			$package_details .= $send_method . '<br>';
			$package_details .= $parcel_type . ': ' . $length . 'x' . $width . 'x' . $height . 'x' . $weight . ' kg';

		} else {

			if ( ! empty( get_option( 'alsendo_connect_settings_general_shipping_method' ) ) ) {
				$send_method = $this->get_template_send_method( get_option( 'alsendo_connect_settings_general_shipping_method' ) );
			}

			if ( ! empty( get_option( 'alsendo_connect_settings_general_parcel_type' ) ) ) {
				$parcel_type = $this->get_parcel_type( get_option( 'alsendo_connect_settings_general_parcel_type' ) );
			}

			$length = get_option( 'alsendo_connect_settings_general_package_length', '' );

			$width  = get_option( 'alsendo_connect_settings_general_package_width', '' );
			$height = get_option( 'alsendo_connect_settings_general_package_height', '' );
			$weight = get_option( 'alsendo_connect_settings_general_package_weight', '' );

			$package_details  = '<br>' . $send_method . '<br>';
			$package_details .= $parcel_type . ': ' . $length . 'x' . $width . 'x' . $height . 'x' . $weight . ' kg';
		}

		return $package_details;
	}


	/**
	 * Retrieves the human-readable label for a parcel type.
	 *
	 * Converts the parcel type code into a translated, user-friendly string.
	 * Labels may vary depending on the configured API type (apaczka vs others).
	 * Supports box, europalette, palette variations, package, and envelope types.
	 *
	 * @param string $type The parcel type code to translate.
	 *
	 * @return string The translated parcel type label, or empty string if type is not recognized.
	 */
	public function get_parcel_type( $type ) {

		$api_type = alsendo_connect()->get_main_settings_api();
		$value    = '';

		if ( 'box' === $type ) {
			$value = esc_html__( 'Box', 'alsendo-connect' );
		}

		if ( 'europalette' === $type ) {
			if ( 'apaczka' === $api_type ) {
				$value = esc_html__( 'Europallet', 'alsendo-connect' );
			} else {
				$value = esc_html__( 'Euro pallet 120x80', 'alsendo-connect' );
			}
		}

		if ( 'palette_60x80' === $type ) {
			if ( 'apaczka' === $api_type ) {
				$value = esc_html__( 'Palette 60x80', 'alsendo-connect' );
			} else {
				$value = esc_html__( 'Half palette 80x60', 'alsendo-connect' );
			}
		}

		if ( 'palette_120x100' === $type ) {
			if ( 'apaczka' === $api_type ) {
				$value = esc_html__( 'Palette 120x100', 'alsendo-connect' );
			} else {
				$value = esc_html__( 'Industrial palette 120x100', 'alsendo-connect' );
			}
		}

		if ( 'palette_120x120' === $type ) {
			if ( 'apaczka' === $api_type ) {
				$value = esc_html__( 'Palette 120x120', 'alsendo-connect' );
			} else {
				$value = esc_html__( 'Industrial palette 120x120', 'alsendo-connect' );
			}
		}

		if ( 'package' === $type ) {
			$value = esc_html__( 'Package', 'alsendo-connect' );
		}

		if ( 'envelope' === $type ) {
			$value = esc_html__( 'Envelope', 'alsendo-connect' );
		}

		if ( 'P2P' === strtoupper( $type ) ) {
			$value = 'P2P';
		}

		if ( 'P2H' === strtoupper( $type ) ) {
			$value = 'P2H';
		}

		if ( 'H2H' === strtoupper( $type ) ) {
			$value = 'H2H';
		}

		if ( 'H2P' === strtoupper( $type ) ) {
			$value = 'H2P';
		}

		return $value;
	}


	/**
	 * Retrieves the human-readable label for a shipment send method.
	 *
	 * Converts the method code into a translated, user-friendly string.
	 * Supports COURIER, POINT, and SELF (including SELF_ prefixed) methods.
	 *
	 * @param string $method The send method code to translate.
	 *
	 * @return string The translated send method label, or empty string if method is not recognized.
	 */
	public function get_template_send_method( $method ) {
		$value = '';

		if ( 'COURIER' === strtoupper( $method ) ) {
			$value = esc_html__( 'Courier pickup request', 'alsendo-connect' );
		}

		if ( 'POINT' === strtoupper( $method ) ) {
			$value = esc_html__( 'Shipment directly at the point', 'alsendo-connect' );
		}

		if ( 'SELF' === strtoupper( $method ) || 0 === strpos( strtoupper( $method ), 'SELF_' ) ) {
			$value = esc_html__( 'Pickup self', 'alsendo-connect' );
		}

		if ( 'ONDEMAND' === strtoupper( $method ) ) {
			$value = 'ONDEMAND';
		}

		if ( 'OCCASIONAL' === strtoupper( $method ) ) {
			$value = 'OCCASIONAL';
		}

		return $value;
	}



	/**
	 * Determines if a parcel is non-standard based on metadata, package templates, or global settings.
	 *
	 * Checks for non-standard parcel status in the following priority order:
	 * 1. Package properties metadata for the specified key
	 * 2. Selected package template settings
	 * 3. Global plugin settings
	 *
	 * @param array  $meta_data The metadata array containing package properties.
	 * @param string $key       The key to check within package properties.
	 *
	 * @return string Returns 'yes' if parcel is non-standard, 'no' otherwise.
	 */
	public function is_parcel_non_standard( $meta_data, $key ) {

		$selected_package_template = get_option( 'alsendo_connect_settings_general_select_package_template' );
		$package_templates_json    = ( new Gateway_Settings_Templates_Helper() )->get_all_templates_json();
		$package_templates         = json_decode( $package_templates_json, true );

		$value = 'no';

		if ( ! empty( $meta_data['package_properties'][ $key ] ) ) {
			$value = $meta_data['package_properties'][ $key ];
		} elseif ( ! empty( $selected_package_template ) && ! empty( $package_templates[ $selected_package_template ] ) ) {
			$data = $package_templates[ $selected_package_template ];

			if ( ! empty( $data['options']['alsendo_connect_settings_general_is_nstd'] ) ) {
				if ( 'yes' === $data['options']['alsendo_connect_settings_general_is_nstd'] ) {
					$value = 'yes';
				}
			}
		} elseif ( ! empty( get_option( 'alsendo_connect_settings_general_is_nstd' ) ) ) {
			if ( 'yes' === get_option( 'alsendo_connect_settings_general_is_nstd' ) ) {
				$value = 'yes';
			}
		}

		return $value;
	}



	public function get_zaslat_shipping_methos_settings( $order_id ) {

		$zaslat_address_id = null;

		$order = wc_get_order( $order_id );

		if ( ! $order || is_wp_error( $order ) ) {
			return array();
		}

		$shipping_method_name = '';
		$method_instance_id   = '';

		foreach ( $order->get_shipping_methods() as $shipping_method ) {
			$method_instance_id   = $shipping_method->get_instance_id();
			$shipping_method_name = $shipping_method->get_method_id();
		}

		$shipping_method_settings_name = 'woocommerce_' . $shipping_method_name . '_' . $method_instance_id . '_settings';

		$shipping_method_settings = get_option( $shipping_method_settings_name );

		/*if ( function_exists( 'wc_get_logger' ) ) {
			\wc_get_logger()->debug( 'shipping_method_settings: $debug_info for order ' . $order_id, array( 'source' => 'zaslat_shipping_method_settings' ) );
			\wc_get_logger()->debug( print_r( $shipping_method_settings, true ), array( 'source' => 'zaslat_shipping_method_settings' ) );
		}*/

		/*if( ! empty($shipping_method_settings['alsendo_connect_linked_zaslat_address']) ) {
			$zaslat_address_id = (int) $shipping_method_settings['alsendo_connect_linked_zaslat_address'];
		} else {
			// legacy.
			$zaslat_address_id = (int) get_option( 'alsendo_connect_settings_general_zaslat_address_id' );
		}*/

		return is_array( $shipping_method_settings ) ? $shipping_method_settings : array();
	}


	/**
	 * Retrieves the merchant's default dispatch point for a specific Ecolet service supplier.
	 *
	 * Fetches the configured default pickup point from WordPress options based on the
	 * service supplier (CARGUS, FAN_COURIER, SAMEDAY, DPD, or GLS).
	 *
	 * @param string $service_supplier The service supplier name to get default point for.
	 *
	 * @return string|null The default dispatch point ID or null if not configured
	 */
	public function get_ecolet_merchant_default_point( $service_supplier ) {

		$merchant_default_point = null;

		if ( 'CARGUS' === $service_supplier ) {
			$merchant_default_point = get_option( 'alsendo_connect_settings_general_dispath_point_cargus' );
		} elseif ( 'FAN_COURIER' === $service_supplier ) {
			$merchant_default_point = get_option( 'alsendo_connect_settings_general_dispath_point_fan_courier' );
		} elseif ( 'SAMEDAY' === $service_supplier ) {
			$merchant_default_point = get_option( 'alsendo_connect_settings_general_dispath_point_sameday' );
		} elseif ( 'DPD' === $service_supplier ) {
			$merchant_default_point = get_option( 'alsendo_connect_settings_general_dispath_point_dpd' );
		} elseif ( 'GLS' === $service_supplier ) {
			$merchant_default_point = get_option( 'alsendo_connect_settings_general_dispath_point_gls' );
		}

		return ! empty( $merchant_default_point ) ? $merchant_default_point : null;
	}


	/**
	 * Validates and formats phone number for Ecolet API based on country code.
	 *
	 * Removes spaces and trims the phone number. For Romanian numbers (RO), removes
	 * the '+40' prefix if present. For other countries, converts '+' prefix to '00'
	 * or prepends '00' if neither prefix exists.
	 *
	 * @param string $phone_number The phone number to validate and format.
	 * @param string $country_code The ISO country code (e.g., 'RO', 'BG').
	 *
	 * @return string The formatted phone number.
	 */
	public function ecolet_phone_validation( $phone_number, $country_code ) {

		$phone_number = trim( $phone_number );

		$phone_number = str_replace( ' ', '', $phone_number );

		$country_code = strtoupper( $country_code );

		if ( 'RO' === $country_code ) {

			if ( strpos( $phone_number, '+4' ) === 0 ) {
				$phone_number = substr( $phone_number, 2 );
			}
		} else {

			if ( strpos( $phone_number, '+' ) === 0 ) {

				$phone_number = '00' . substr( $phone_number, 1 );
			} elseif ( strpos( $phone_number, '00' ) !== 0 ) {

				$phone_number = '00' . $phone_number;
			}
		}

		return $phone_number;
	}
}
