<?php
/**
 * Amazon Order Manager
 *
 * @package    MOMCS_Sync
 * @subpackage MOMCS_Sync/includes/common/services/amazon
 * @author     miniOrange
 */

declare(strict_types=1);

namespace MOMCS_Sync\Includes\Common\Services\Amazon;

use MOMCS_Sync\Includes\Common\Utils\Logger;
use MOMCS_Sync\Includes\Common\Exceptions\Sync_Exception;
use MOMCS_Sync\Includes\Common\Utils\Asin_Helper;
use MOMCS_Sync\Includes\Common\Utils\Order_Status_Mapper;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class for managing Amazon orders and syncing to WooCommerce.
 */
class Order_Manager {
	/**
	 * Logger instance.
	 *
	 * @var Logger
	 */
	private $logger;

	/**
	 * Constructor.
	 */
	public function __construct() {
		$this->logger = new Logger( 'order-manager' );
	}


	/**
	 * Create WooCommerce order from Amazon order.
	 *
	 * @param array  $amazon_order Amazon order data.
	 * @param string $channel_uuid Optional. The channel UUID for this order.
	 * @return int WooCommerce order ID.
	 * @throws Sync_Exception If the order already exists or creation fails.
	 */
	public function create_woocommerce_order( $amazon_order, $channel_uuid = '' ) {
		try {
			global $wpdb;

			// Debug log.
			$this->logger->debug( 'Creating WooCommerce order for Amazon order: ' . $amazon_order['AmazonOrderId'] );

			// Check if order already exists.
			$existing_order_id = $this->get_woocommerce_order_id_by_amazon_id( $amazon_order['AmazonOrderId'] );
			if ( $existing_order_id ) {
				$this->logger->debug( 'Order already exists with ID: ' . $existing_order_id );
				throw new Sync_Exception( 'Order already exists in WooCommerce.' );
			}

			// Create order.
			$order = wc_create_order();
			if ( is_wp_error( $order ) ) {
				$this->logger->debug( 'Failed to create WooCommerce order: ' . $order->get_error_message() );
				throw new Sync_Exception( 'Failed to create WooCommerce order: ' . $order->get_error_message() );
			}

			// Set billing details.
			$this->set_billing_details( $order, $amazon_order );

			// Set shipping details.
			$this->set_shipping_details( $order, $amazon_order );

			// If Amazon did not return a ship-to block, mirror billing so WC shows a full shipping address.
			$this->sync_shipping_address_from_billing_if_empty( $order );

			// Add order items.
			if ( isset( $amazon_order['OrderItems'] ) ) {
				foreach ( $amazon_order['OrderItems'] as $item ) {
					$this->add_order_item( $order, $item );
				}
			}

			// Shipping method / fee line from Amazon (service level + per-item ShippingPrice).
			$this->add_amazon_shipping_line_item( $order, $amazon_order );

			// Store all Amazon order data as meta.
			$this->store_amazon_order_meta( $order, $amazon_order, $channel_uuid );

			// Map Amazon order status to WooCommerce status.
			$amazon_status = $amazon_order['OrderStatus'] ?? '';
			$mapped_status = Order_Status_Mapper::map_amazon_status_to_woocommerce( $amazon_status, $amazon_order );

			$this->logger->debug(
				sprintf(
					'Mapping Amazon status "%s" to WooCommerce status "%s" for order %s',
					$amazon_status,
					$mapped_status,
					$amazon_order['AmazonOrderId']
				)
			);

			// Set order status based on Amazon status.
			$order->update_status(
				$mapped_status,
				sprintf(
					/* translators: %s: Amazon order status */
					__( 'Order imported from Amazon with status: %s', 'multi-channel-for-woocommerce' ),
					$amazon_status
				)
			);

			// Currency from Amazon when present.
			if ( isset( $amazon_order['OrderTotal']['CurrencyCode'] ) && is_string( $amazon_order['OrderTotal']['CurrencyCode'] ) ) {
				$order->set_currency( sanitize_text_field( $amazon_order['OrderTotal']['CurrencyCode'] ) );
			}

			// If Amazon provided order total, sync it.
			if ( isset( $amazon_order['OrderTotal']['Amount'] ) ) {
				$order->set_total( (float) $amazon_order['OrderTotal']['Amount'] );
			}

			$this->add_amazon_customer_details_sync_note( $order, $amazon_order );

			// Save order.
			$order->save();

			$this->logger->debug( 'Successfully created WooCommerce order ' . $order->get_id() . ' for Amazon order ' . $amazon_order['AmazonOrderId'] );
			return $order->get_id();
		} catch ( \Exception $e ) {
			$this->logger->error( 'Error creating WooCommerce order: ' . esc_html( $e->getMessage() ) );
			throw new Sync_Exception( esc_html( 'Error creating WooCommerce order: ' . $e->getMessage() ) );
		}
	}

	/**
	 * Store Amazon order data in WooCommerce order meta.
	 *
	 * @param WC_Order $order WooCommerce order.
	 * @param array    $amazon_order Amazon order data.
	 * @param string   $channel_uuid Optional. The channel UUID for this order.
	 * @return void
	 * @throws \Exception If the order meta data cannot be saved.
	 * @throws \RuntimeException If the order meta data cannot be saved.
	 */
	private function store_amazon_order_meta( $order, $amazon_order, $channel_uuid = '' ) {
		// Store basic Amazon order details.
		$order->update_meta_data( '_amazon_order_id', $amazon_order['AmazonOrderId'] );
		$order->update_meta_data( '_amazon_order_status', $amazon_order['OrderStatus'] );
		$order->update_meta_data( '_amazon_fulfillment_channel', $amazon_order['FulfillmentChannel'] );
		$order->update_meta_data( '_amazon_purchase_date', $amazon_order['PurchaseDate'] );
		$order->update_meta_data( '_amazon_last_update_date', $amazon_order['LastUpdateDate'] );

		// Store channel UUID if provided.
		if ( ! empty( $channel_uuid ) ) {
			$order->update_meta_data( '_amazon_channel_uuid', $channel_uuid );
		}

		// Store marketplace ID if available.
		if ( isset( $amazon_order['MarketplaceId'] ) ) {
			$order->update_meta_data( '_amazon_marketplace_id', $amazon_order['MarketplaceId'] );
		}

		// Store buyer info.
		if ( isset( $amazon_order['BuyerInfo'] ) ) {
			$order->update_meta_data( '_amazon_buyer_info', $amazon_order['BuyerInfo'] );
		}

		// Store shipping info.
		if ( isset( $amazon_order['ShippingAddress'] ) ) {
			$order->update_meta_data( '_amazon_shipping_address', $amazon_order['ShippingAddress'] );
		}

		// Store order items.
		if ( isset( $amazon_order['OrderItems'] ) ) {
			$order->update_meta_data( '_amazon_order_items', $amazon_order['OrderItems'] );
		}

		// Store order totals.
		if ( isset( $amazon_order['OrderTotal'] ) ) {
			$order->update_meta_data( '_amazon_order_total', $amazon_order['OrderTotal'] );
		}

		// Store the complete Amazon order data for reference.
		$order->update_meta_data( '_amazon_order_data', $amazon_order );
	}

	/**
	 * Get WooCommerce order ID by Amazon order ID.
	 *
	 * @param string $amazon_order_id Amazon order ID.
	 * @return int|false Order ID if found, false otherwise.
	 */
	public function get_woocommerce_order_id_by_amazon_id( $amazon_order_id ) {
		// Get all WooCommerce order statuses and strip the 'wc-' prefix.
		$all_statuses = array_map(
			function ( $status ) {
				return str_replace( 'wc-', '', $status );
			},
			array_keys( wc_get_order_statuses() )
		);

		$orders = wc_get_orders(
			array(
				'limit'      => 1,
				'type'       => 'shop_order',
				'status'     => $all_statuses,
				'orderby'    => 'ID',
				'order'      => 'DESC',
				'paginate'   => false,
				'return'     => 'ids',
				'meta_key'   => '_amazon_order_id', //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Required to get order ID by Amazon order ID.
				'meta_value' => $amazon_order_id, //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value -- Required to get order ID by Amazon order ID.
			)
		);

		return ! empty( $orders ) ? (int) $orders[0] : false;
	}

	/**
	 * Get Amazon orders from WooCommerce.
	 *
	 * @param array $args Query arguments.
	 * @return array Array of orders with Amazon data.
	 */
	public function get_amazon_orders( $args = array() ) {
		// Get all WooCommerce order statuses and strip the 'wc-' prefix.
		$all_statuses = array_map(
			function ( $status ) {
				return str_replace( 'wc-', '', $status );
			},
			array_keys( wc_get_order_statuses() )
		);

		$default_args = array(
			'posts_per_page' => 10,
			'paged'          => 1,
			'post_status'    => $all_statuses,
		);

		$args = wp_parse_args( $args, $default_args );

		$wc_query_args = array(
			'limit'      => $args['posts_per_page'],
			'page'       => $args['paged'],
			'type'       => 'shop_order',
			'status'     => $args['post_status'],
			'orderby'    => 'ID',
			'order'      => 'DESC',
			'paginate'   => true,
			'return'     => 'objects',
			'meta_query' => array( //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Required to get orders with Amazon order ID.
				array(
					'key'     => '_amazon_order_id',
					'compare' => 'EXISTS',
				),
			),
		);

		// Additional filters.
		if ( ! empty( $args['amazon_status'] ) ) {
			$wc_query_args['meta_query'][] = array(
				'key'   => '_amazon_order_status',
				'value' => $args['amazon_status'],
			);
		}

		if ( ! empty( $args['fulfillment_channel'] ) ) {
			$wc_query_args['meta_query'][] = array(
				'key'   => '_amazon_fulfillment_channel',
				'value' => $args['fulfillment_channel'],
			);
		}

		// Date range filter.
		if ( ! empty( $args['date_from'] ) || ! empty( $args['date_to'] ) ) {
			$date_query = array(
				'key'  => '_amazon_purchase_date',
				'type' => 'DATETIME',
			);

			if ( ! empty( $args['date_from'] ) && ! empty( $args['date_to'] ) ) {
				$date_query['value']   = array( $args['date_from'] . ' 00:00:00', $args['date_to'] . ' 23:59:59' );
				$date_query['compare'] = 'BETWEEN';
			} elseif ( ! empty( $args['date_from'] ) ) {
				$date_query['value']   = $args['date_from'] . ' 00:00:00';
				$date_query['compare'] = '>=';
			} else {
				$date_query['value']   = $args['date_to'] . ' 23:59:59';
				$date_query['compare'] = '<=';
			}

			$wc_query_args['meta_query'][] = $date_query;
		}

		// Search filter.
		if ( ! empty( $args['search'] ) ) {
			$wc_query_args['meta_query'][] = array(
				'relation' => 'OR',
				array(
					'key'     => '_amazon_order_id',
					'value'   => $args['search'],
					'compare' => 'LIKE',
				),
				array(
					'key'     => '_amazon_order_status',
					'value'   => $args['search'],
					'compare' => 'LIKE',
				),
			);
		}

		$query_results = wc_get_orders( $wc_query_args );
		$total         = isset( $query_results->total ) ? (int) $query_results->total : 0;
		$pages         = isset( $query_results->max_num_pages ) ? (int) $query_results->max_num_pages : 1;

		$orders_formatted = array();
		foreach ( $query_results->orders as $order ) {
			$amazon_data = $order->get_meta( '_amazon_order_data' );
			if ( empty( $amazon_data ) ) {
				// Build minimal order data from individual meta fields.
				$amazon_data = array(
					'AmazonOrderId'      => $order->get_meta( '_amazon_order_id' ),
					'OrderStatus'        => $order->get_meta( '_amazon_order_status' ),
					'FulfillmentChannel' => $order->get_meta( '_amazon_fulfillment_channel' ),
				);

				// Add order total if available.
				$order_total = $order->get_meta( '_amazon_order_total' );
				if ( ! empty( $order_total ) ) {
					$amazon_data['OrderTotal'] = $order_total;
				} else {
					// Fallback to WooCommerce order total.
					$amazon_data['OrderTotal'] = array(
						'CurrencyCode' => $order->get_currency(),
						'Amount'       => $order->get_total(),
					);
				}

				// Add purchase date.
				$purchase_date = $order->get_meta( '_amazon_purchase_date' );
				if ( ! empty( $purchase_date ) ) {
					$amazon_data['PurchaseDate'] = $purchase_date;
				} else {
					$amazon_data['PurchaseDate'] = $order->get_date_created()->date( 'c' );
				}

				// Add order items if available.
				$order_items = $order->get_meta( '_amazon_order_items' );
				if ( ! empty( $order_items ) ) {
					$amazon_data['OrderItems'] = $order_items;
				} else {
					$amazon_data['OrderItems'] = array();
				}
			}

			// Ensure OrderTotal exists even if full data is present.
			if ( ! isset( $amazon_data['OrderTotal'] ) || empty( $amazon_data['OrderTotal'] ) ) {
				$amazon_data['OrderTotal'] = array(
					'CurrencyCode' => $order->get_currency(),
					'Amount'       => $order->get_total(),
				);
			}

			// Ensure PurchaseDate exists.
			if ( ! isset( $amazon_data['PurchaseDate'] ) || empty( $amazon_data['PurchaseDate'] ) ) {
				$amazon_data['PurchaseDate'] = $order->get_date_created()->date( 'c' );
			}

			// Ensure OrderItems exists.
			if ( ! isset( $amazon_data['OrderItems'] ) ) {
				$amazon_data['OrderItems'] = array();
			}

			$amazon_data['WooCommerceOrderId'] = $order->get_id();
			$amazon_data['WooCommerceStatus']  = $order->get_status();

			$orders_formatted[] = $amazon_data;
		}

		return array(
			'orders'    => $orders_formatted,
			'total'     => $total,
			'max_pages' => $pages,
		);
	}

	/**
	 * Normalize buyer info from getOrderBuyerInfo API payload.
	 *
	 * Amazon returns BuyerEmail, BuyerName, etc. on the payload root — not under BuyerInfo.
	 *
	 * @param array $payload Decoded JSON `payload` from getOrderBuyerInfo.
	 * @return array<string,mixed> Canonical BuyerInfo for internal use.
	 */
	public static function normalize_buyer_info_from_api_response( array $payload ): array {
		if ( isset( $payload['BuyerInfo'] ) && is_array( $payload['BuyerInfo'] ) ) {
			return $payload['BuyerInfo'];
		}

		$tax = array();
		if ( isset( $payload['BuyerTaxInfo'] ) && is_array( $payload['BuyerTaxInfo'] ) ) {
			$tax = $payload['BuyerTaxInfo'];
		}

		return array(
			'BuyerEmail'          => isset( $payload['BuyerEmail'] ) ? (string) $payload['BuyerEmail'] : '',
			'BuyerName'           => isset( $payload['BuyerName'] ) ? (string) $payload['BuyerName'] : '',
			'BuyerCounty'         => isset( $payload['BuyerCounty'] ) ? (string) $payload['BuyerCounty'] : '',
			'BuyerTaxInfo'        => $tax,
			'PurchaseOrderNumber' => isset( $payload['PurchaseOrderNumber'] ) ? (string) $payload['PurchaseOrderNumber'] : '',
		);
	}

	/**
	 * Normalize shipping address from getOrderAddress API payload.
	 *
	 * @param array $payload Decoded JSON `payload` from getOrderAddress.
	 * @return array<string,mixed> ShippingAddress block.
	 */
	public static function normalize_shipping_address_from_api_response( array $payload ): array {
		if ( isset( $payload['ShippingAddress'] ) && is_array( $payload['ShippingAddress'] ) ) {
			return $payload['ShippingAddress'];
		}

		if ( isset( $payload['AddressLine1'] ) || isset( $payload['Name'] ) || isset( $payload['City'] ) ) {
			return $payload;
		}

		return array();
	}

	/**
	 * Split a full name into first and last for WooCommerce fields.
	 *
	 * @param string $full Raw full name.
	 * @return array{0:string,1:string} First name, last name.
	 */
	private function split_full_name( string $full ): array {
		$full = trim( $full );
		if ( '' === $full ) {
			return array( '', '' );
		}

		$parts = preg_split( '/\s+/u', $full, 2 );
		$first = isset( $parts[0] ) ? sanitize_text_field( $parts[0] ) : '';
		$last  = isset( $parts[1] ) ? sanitize_text_field( $parts[1] ) : '';

		return array( $first, $last );
	}

	/**
	 * Resolve WooCommerce address line 1. Amazon often omits street (PII); WC may show "no address" if line 1 is blank.
	 *
	 * @param array<string,mixed> $address Amazon ShippingAddress block.
	 * @return string Sanitized line 1.
	 */
	private function resolve_address_line_1( array $address ): string {
		$line1 = isset( $address['AddressLine1'] ) ? trim( (string) $address['AddressLine1'] ) : '';
		if ( '' !== $line1 ) {
			return sanitize_text_field( $line1 );
		}

		$parts = array();
		$pc    = isset( $address['PostalCode'] ) ? trim( (string) $address['PostalCode'] ) : '';
		$city  = isset( $address['City'] ) ? trim( (string) $address['City'] ) : '';
		$reg   = isset( $address['StateOrRegion'] ) ? trim( (string) $address['StateOrRegion'] ) : '';

		if ( '' !== $pc ) {
			$parts[] = $pc;
		}
		if ( '' !== $city ) {
			$parts[] = $city;
		}
		if ( '' !== $reg ) {
			$parts[] = $reg;
		}

		if ( empty( $parts ) ) {
			return '';
		}

		return sanitize_text_field( implode( ', ', $parts ) );
	}

	/**
	 * Combine Amazon AddressLine2 and AddressLine3 for WooCommerce address line 2.
	 *
	 * @param array<string,mixed> $address Amazon ShippingAddress.
	 * @return string Sanitized combined line.
	 */
	private function combine_address_lines_2_and_3( array $address ): string {
		$line2 = isset( $address['AddressLine2'] ) ? trim( (string) $address['AddressLine2'] ) : '';
		$line3 = isset( $address['AddressLine3'] ) ? trim( (string) $address['AddressLine3'] ) : '';

		if ( '' === $line2 && '' === $line3 ) {
			return '';
		}

		if ( '' === $line3 ) {
			return sanitize_text_field( $line2 );
		}

		if ( '' === $line2 ) {
			return sanitize_text_field( $line3 );
		}

		return sanitize_text_field( $line2 . ', ' . $line3 );
	}

	/**
	 * Sanitize phone number for WooCommerce order fields.
	 *
	 * @param mixed $phone Raw phone from Amazon.
	 * @return string Sanitized phone.
	 */
	private function sanitize_order_phone( $phone ): string {
		$raw = sanitize_text_field( (string) $phone );
		if ( function_exists( 'wc_sanitize_phone' ) ) {
			return wc_sanitize_phone( $raw );
		}

		return $raw;
	}

	/**
	 * Add a private order note only when Amazon APIs did not return complete customer data.
	 *
	 * @param WC_Order $order        WooCommerce order.
	 * @param array    $amazon_order Merged Amazon order (buyer + address).
	 * @return void
	 */
	private function add_amazon_customer_details_sync_note( $order, array $amazon_order ): void {
		$buyer   = isset( $amazon_order['BuyerInfo'] ) && is_array( $amazon_order['BuyerInfo'] ) ? $amazon_order['BuyerInfo'] : array();
		$address = isset( $amazon_order['ShippingAddress'] ) && is_array( $amazon_order['ShippingAddress'] ) ? $amazon_order['ShippingAddress'] : array();

		$has_email = ! empty( $buyer['BuyerEmail'] );
		$has_name  = ! empty( $buyer['BuyerName'] ) || ! empty( $address['Name'] );
		$has_addr  = ! empty( $address['AddressLine1'] ) || ! empty( $address['City'] ) || ! empty( $address['PostalCode'] );
		$has_phone = ! empty( $address['Phone'] );

		$sync_incomplete = ! $has_email || ! $has_name || ! $has_addr || ! $has_phone;

		if ( ! $sync_incomplete ) {
			return;
		}

		$plugin_name = __( 'Multi-channel for WooCommerce', 'multi-channel-for-woocommerce' );
		$note        = sprintf(
			/* translators: 1: Plugin name. 2: Support email address. */
			__( '[%1$s] Some customer details could not be synced from Amazon. For assistance, contact %2$s.', 'multi-channel-for-woocommerce' ),
			$plugin_name,
			'apisupport@xecurify.com'
		);

		$order->add_order_note( $note, false, false );
	}

	/**
	 * Set billing details for WooCommerce order.
	 *
	 * @param WC_Order $order WooCommerce order.
	 * @param array    $amazon_order Amazon order data.
	 */
	private function set_billing_details( $order, $amazon_order ) {
		$buyer   = isset( $amazon_order['BuyerInfo'] ) && is_array( $amazon_order['BuyerInfo'] ) ? $amazon_order['BuyerInfo'] : array();
		$address = isset( $amazon_order['ShippingAddress'] ) && is_array( $amazon_order['ShippingAddress'] ) ? $amazon_order['ShippingAddress'] : array();

		if ( ! empty( $buyer['BuyerEmail'] ) ) {
			$email = sanitize_email( (string) $buyer['BuyerEmail'] );
			if ( $email ) {
				$order->set_billing_email( $email );
			}
		}

		$full_name = '';
		if ( ! empty( $buyer['BuyerName'] ) ) {
			$full_name = trim( (string) $buyer['BuyerName'] );
		} elseif ( ! empty( $address['Name'] ) ) {
			$full_name = trim( (string) $address['Name'] );
		}

		$name_parts = $this->split_full_name( $full_name );
		$order->set_billing_first_name( $name_parts[0] );
		$order->set_billing_last_name( $name_parts[1] );

		if ( ! empty( $buyer['BuyerTaxInfo']['CompanyLegalName'] ) ) {
			$order->set_billing_company( sanitize_text_field( (string) $buyer['BuyerTaxInfo']['CompanyLegalName'] ) );
		} elseif ( ! empty( $amazon_order['BuyerCompanyName'] ) ) {
			$order->set_billing_company( sanitize_text_field( (string) $amazon_order['BuyerCompanyName'] ) );
		}

		if ( ! empty( $buyer['PurchaseOrderNumber'] ) ) {
			$order->update_meta_data( '_amazon_buyer_purchase_order_number', sanitize_text_field( (string) $buyer['PurchaseOrderNumber'] ) );
		}

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

		$order->set_billing_address_1( $this->resolve_address_line_1( $address ) );
		$order->set_billing_address_2( $this->combine_address_lines_2_and_3( $address ) );
		$order->set_billing_city( sanitize_text_field( (string) ( $address['City'] ?? '' ) ) );

		$state = isset( $address['StateOrRegion'] ) ? (string) $address['StateOrRegion'] : '';
		if ( '' === $state && ! empty( $address['County'] ) ) {
			$state = (string) $address['County'];
		}
		$order->set_billing_state( sanitize_text_field( $state ) );
		$order->set_billing_postcode( sanitize_text_field( (string) ( $address['PostalCode'] ?? '' ) ) );
		$order->set_billing_country( sanitize_text_field( (string) ( $address['CountryCode'] ?? '' ) ) );

		if ( ! empty( $address['Phone'] ) ) {
			$order->set_billing_phone( $this->sanitize_order_phone( $address['Phone'] ) );
		}
	}

	/**
	 * Set shipping details for WooCommerce order.
	 *
	 * @param WC_Order $order WooCommerce order.
	 * @param array    $amazon_order Amazon order data.
	 */
	private function set_shipping_details( $order, $amazon_order ) {
		$buyer   = isset( $amazon_order['BuyerInfo'] ) && is_array( $amazon_order['BuyerInfo'] ) ? $amazon_order['BuyerInfo'] : array();
		$address = isset( $amazon_order['ShippingAddress'] ) && is_array( $amazon_order['ShippingAddress'] ) ? $amazon_order['ShippingAddress'] : array();

		if ( empty( $address ) ) {
			if ( ! empty( $buyer['BuyerName'] ) ) {
				$parts = $this->split_full_name( trim( (string) $buyer['BuyerName'] ) );
				$order->set_shipping_first_name( $parts[0] );
				$order->set_shipping_last_name( $parts[1] );
			}
			return;
		}

		$full_name = '';
		if ( ! empty( $address['Name'] ) ) {
			$full_name = trim( (string) $address['Name'] );
		} elseif ( ! empty( $buyer['BuyerName'] ) ) {
			$full_name = trim( (string) $buyer['BuyerName'] );
		}

		$name_parts = $this->split_full_name( $full_name );
		$order->set_shipping_first_name( $name_parts[0] );
		$order->set_shipping_last_name( $name_parts[1] );

		if ( ! empty( $buyer['BuyerTaxInfo']['CompanyLegalName'] ) ) {
			$order->set_shipping_company( sanitize_text_field( (string) $buyer['BuyerTaxInfo']['CompanyLegalName'] ) );
		} elseif ( ! empty( $amazon_order['BuyerCompanyName'] ) ) {
			$order->set_shipping_company( sanitize_text_field( (string) $amazon_order['BuyerCompanyName'] ) );
		}

		$order->set_shipping_address_1( $this->resolve_address_line_1( $address ) );
		$order->set_shipping_address_2( $this->combine_address_lines_2_and_3( $address ) );
		$order->set_shipping_city( sanitize_text_field( (string) ( $address['City'] ?? '' ) ) );

		$state = isset( $address['StateOrRegion'] ) ? (string) $address['StateOrRegion'] : '';
		if ( '' === $state && ! empty( $address['County'] ) ) {
			$state = (string) $address['County'];
		}
		$order->set_shipping_state( sanitize_text_field( $state ) );
		$order->set_shipping_postcode( sanitize_text_field( (string) ( $address['PostalCode'] ?? '' ) ) );
		$order->set_shipping_country( sanitize_text_field( (string) ( $address['CountryCode'] ?? '' ) ) );

		if ( ! empty( $address['Phone'] ) ) {
			$order->set_shipping_phone( $this->sanitize_order_phone( $address['Phone'] ) );
		}
	}

	/**
	 * Copy billing address to shipping when Amazon returned no ship-to but billing is filled.
	 *
	 * @param WC_Order $order WooCommerce order.
	 * @return void
	 */
	private function sync_shipping_address_from_billing_if_empty( $order ) {
		$ship_line1 = trim( (string) $order->get_shipping_address_1() );
		if ( '' !== $ship_line1 ) {
			return;
		}

		$bill_line1 = trim( (string) $order->get_billing_address_1() );
		if ( '' === $bill_line1 ) {
			return;
		}

		$order->set_shipping_first_name( $order->get_billing_first_name() );
		$order->set_shipping_last_name( $order->get_billing_last_name() );
		$order->set_shipping_company( $order->get_billing_company() );
		$order->set_shipping_address_1( $order->get_billing_address_1() );
		$order->set_shipping_address_2( $order->get_billing_address_2() );
		$order->set_shipping_city( $order->get_billing_city() );
		$order->set_shipping_state( $order->get_billing_state() );
		$order->set_shipping_postcode( $order->get_billing_postcode() );
		$order->set_shipping_country( $order->get_billing_country() );

		$bill_phone = (string) $order->get_billing_phone();
		if ( '' !== $bill_phone ) {
			$order->set_shipping_phone( $bill_phone );
		}
	}

	/**
	 * Add a WooCommerce shipping line from Amazon ship service level and item ShippingPrice totals.
	 *
	 * @param WC_Order $order        WooCommerce order.
	 * @param array    $amazon_order Amazon order payload.
	 * @return void
	 */
	private function add_amazon_shipping_line_item( $order, array $amazon_order ) {
		$shipping_total = 0.0;
		if ( ! empty( $amazon_order['OrderItems'] ) && is_array( $amazon_order['OrderItems'] ) ) {
			foreach ( $amazon_order['OrderItems'] as $line ) {
				if ( ! is_array( $line ) ) {
					continue;
				}
				if ( isset( $line['ShippingPrice']['Amount'] ) ) {
					$shipping_total += (float) $line['ShippingPrice']['Amount'];
				}
			}
		}

		$method_title = '';
		if ( ! empty( $amazon_order['ShipServiceLevel'] ) ) {
			$method_title = sanitize_text_field( (string) $amazon_order['ShipServiceLevel'] );
		} elseif ( ! empty( $amazon_order['ShipmentServiceLevelCategory'] ) ) {
			$method_title = sanitize_text_field( (string) $amazon_order['ShipmentServiceLevelCategory'] );
		}

		if ( $shipping_total <= 0 && '' === $method_title ) {
			return;
		}

		if ( '' === $method_title ) {
			$method_title = __( 'Amazon shipping', 'multi-channel-for-woocommerce' );
		}

		$item = new \WC_Order_Item_Shipping();
		$item->set_method_title( $method_title );
		$item->set_method_id( 'amazon' );
		$item->set_total( wc_format_decimal( $shipping_total ) );
		$order->add_item( $item );
	}

	/**
	 * Add item to WooCommerce order.
	 *
	 * @param WC_Order $order WooCommerce order.
	 * @param array    $item Amazon order item.
	 */
	private function add_order_item( $order, $item ) {
		// Try to find matching product in WooCommerce.
		$product_id = wc_get_product_id_by_sku( $item['SellerSKU'] );

		if ( ! $product_id ) {
			// Create a simple product if no match found.
			$product = new \WC_Product_Simple();
			$product->set_name( $item['Title'] );
			$product->set_sku( $item['SellerSKU'] );
			$product->set_regular_price( $item['ItemPrice']['Amount'] );
			$product->save();
			$product_id = $product->get_id();

			// Save Amazon-specific meta.
			if ( isset( $item['ASIN'] ) ) {
				Asin_Helper::set_product_asin( $product_id, sanitize_text_field( $item['ASIN'] ) );
			}
			if ( isset( $item['ConditionId'] ) ) {
				update_post_meta( $product_id, '_momcs_amz_condition', sanitize_text_field( strtolower( $item['ConditionId'] ) ) );
			}
		} else {
			// Product exists; update missing meta if not already set.
			if ( isset( $item['ASIN'] ) && ! Asin_Helper::product_has_asin( $product_id ) ) {
				Asin_Helper::set_product_asin( $product_id, sanitize_text_field( $item['ASIN'] ) );
			}
			if ( isset( $item['ConditionId'] ) && ! get_post_meta( $product_id, '_momcs_amz_condition', true ) ) {
				update_post_meta( $product_id, '_momcs_amz_condition', sanitize_text_field( strtolower( $item['ConditionId'] ) ) );
			}
		}

		// Add item to order.
		$order->add_product(
			wc_get_product( $product_id ),
			$item['QuantityOrdered'],
			array(
				'subtotal' => $item['ItemPrice']['Amount'] * $item['QuantityOrdered'],
				'total'    => $item['ItemPrice']['Amount'] * $item['QuantityOrdered'],
			)
		);
	}
}
