<?php

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

/**
 * Handles synchronization of WooCommerce orders with Zoho CRM Sales Orders and Deals modules.
 *
 * Provides methods for syncing, updating, and cancelling orders, as well as mapping fields and handling contacts/accounts.
 */
class CMBIRD_ZCRM_SalesOrder {

	/**
	 * Zoho CRM Modules handler instance.
	 *
	 * @var CMBIRD_ZCRM_Modules
	 */
	protected $zcrm_modules;

	/**
	 * Zoho CRM base URL.
	 *
	 * @var string
	 */
	protected $zoho_crm_url;

	/**
	 * Custom fields for Zoho Sales Orders.
	 *
	 * @var array
	 */
	protected $zcrm_custom_fields;

	/**
	 * Zoho CRM Product handler instance.
	 *
	 * @var CMBIRD_ZCRM_Product
	 */
	protected $zcrm_product;

	/**
	 * Constructor
	 *
	 * Initializes the class, setting the Zoho CRM Modules object, the Zoho CRM URL,
	 * and the custom fields for the Sales Orders module. Also initializes the
	 * Zoho CRM Products object.
	 */
	public function __construct() {
		$this->zcrm_modules = new CMBIRD_ZCRM_Modules();
		$this->zoho_crm_url = rtrim( get_option( 'cmbird_zoho_crm_url' ), '/' ) . '/';
		// get the option for custom fields.
		$this->zcrm_custom_fields = get_option( 'zcrm_sales_orders_fields', array() );
		// Initialize product class for product-related operations.
		$this->zcrm_product = new CMBIRD_ZCRM_Product();
	}

	/**
	 * Log messages using WooCommerce logger if available, otherwise fallback to error_log
	 *
	 * @param string $message The message to log.
	 * @param string $level Log level: debug, info, notice, warning, error, critical, alert, emergency.
	 */
	private function log( $message, $level = 'info' ) {
		if ( function_exists( 'wc_get_logger' ) ) {
			$logger = wc_get_logger();
			$logger->log( $level, $message, array( 'source' => 'commercebird' ) );
		}
	}

	/**
	 * Get the module name for order sync (Sales_Orders or Deals)
	 *
	 * @return string
	 */
	private function get_order_module_name() {
		$sync_as_deals = get_option( 'cmbird_zcrm_sync_as_deals', false );
		return $sync_as_deals ? 'Deals' : 'Sales_Orders';
	}

	/**
	 * Get the meta key for storing Zoho record ID based on module
	 *
	 * @return string
	 */
	private function get_zoho_id_meta_key() {
		$module_name = $this->get_order_module_name();
		return 'Deals' === $module_name ? 'zcrm_deals_id' : 'zcrm_sales_order_id';
	}


	/**
	 * Sync a WooCommerce order to Zoho CRM (Sales_Orders or Deals)
	 *
	 * @param int $order_id The WooCommerce order ID.
	 *
	 * @return void
	 *
	 * @since 1.0.0
	 */
	public function cmbird_zcrm_order_sync( $order_id ) {
		// $fd = fopen( __DIR__ . '/cmbird_zcrm_order_sync.txt', 'w+' );
		$order = wc_get_order( $order_id );
		if ( ! $order || ! $order->get_billing_email() ) {
			return;
		}

		$contact_id = $this->get_or_resolve_contact_id( $order );
		if ( is_wp_error( $contact_id ) ) {
			// save error as order note.
			$order->add_order_note( 'Zoho CRM Contact Error: ' . $contact_id->get_error_message() );
			return;
		}

		$account_id = $this->get_or_resolve_account_id( $order );
		if ( is_wp_error( $account_id ) ) {
			// save error as order note.
			$order->add_order_note( 'Zoho Account lookup failed: ' . $account_id->get_error_message() );
			return;
		}

		// Step 1. if zcrm record id is in the order meta, we will update the record.
		$meta_key  = $this->get_zoho_id_meta_key();
		$record_id = $order->get_meta( $meta_key, true );
		if ( $record_id ) {
			$module_name = $this->get_order_module_name();
			$body        = $this->format_order_for_module( $order, $contact_id, $account_id, $module_name, true );
			// Save the request body for debugging purposes.
			$order->update_meta_data( 'zcrm_request_body', wp_json_encode( $body ) );
			// log the body for debugging.
			// fwrite( $fd, 'Zoho Record Update Body: ' . wp_json_encode( $body ) . PHP_EOL );
			// Update the existing record in Zoho.
			$response = $this->zcrm_modules->cmbird_update_record( $module_name, $record_id, $body );
			if ( is_wp_error( $response ) ) {
				// log the error message as order note.
				$order->add_order_note( 'Zoho CRM Update Failed: ' . $response->get_error_message() );
				$order->save();
				return;
			}
			$order->add_order_note( 'Zoho CRM ' . $module_name . ' updated successfully with ID: ' . $record_id );
			// fwrite( $fd, 'Zoho Record updated successfully with ID: ' . $record_id . PHP_EOL );
			$order->save();
			return;
		}
		$module_name = $this->get_order_module_name();
		$body        = $this->format_order_for_module( $order, $contact_id, $account_id, $module_name );

		// Save the request body for debugging purposes.
		$order->update_meta_data( 'zcrm_request_body', wp_json_encode( $body ) );

		// Debug logging for tax-inclusive pricing issues.
		if ( get_option( 'woocommerce_prices_include_tax' ) === 'yes' ) {
			$this->log(
				'CommerceBird Debug - Tax Inclusive Order Sync: ' . wp_json_encode(
					array(
						'order_id'           => $order->get_id(),
						'prices_include_tax' => true,
						'order_total'        => $order->get_total(),
						'body_sample'        => isset( $body['data'][0]['Ordered_Items'][0] ) ? $body['data'][0]['Ordered_Items'][0] : 'No items',
					)
				),
				'debug'
			);
		}

		// Step 2. If no existing sales order ID, create a new one.
		$response = $this->zcrm_modules->cmbird_create_record( $module_name, $body );

		if ( is_wp_error( $response ) ) {
			// log the entire error object for debugging.
			$this->log( 'Zoho CRM Create Record Error: ' . wp_json_encode( $response ), 'error' );
			// log the error message as order note.
			$order->add_order_note( 'Zoho CRM Sync Failed: ' . $response->get_error_message() );
			$order->save();
			return;
		} else {
			$record_id   = $response->data[0]->details->id;
			$meta_key    = $this->get_zoho_id_meta_key();
			$module_name = $this->get_order_module_name();

			// For Sales Orders, also handle line items.
			if ( 'Sales_Orders' === $module_name ) {
				// Get the Sales Order and save the id of Ordered_Items.
				$sales_order_record = $this->zcrm_modules->cmbird_get_record( $module_name, $record_id );
				if ( ! empty( $sales_order_record->data[0]->Ordered_Items ) ) {
					foreach ( $sales_order_record->data[0]->Ordered_Items as $item ) {
						$line_item_id = $item->id;
						// Get Product_Code from Zoho.
						$product_code = isset( $item->Product_Name->Product_Code ) ? $item->Product_Name->Product_Code : '';
						if ( empty( $product_code ) ) {
							continue;
						}
						// Loop through Woo order items and match by SKU.
						foreach ( $order->get_items() as $order_item ) {
							$product = $order_item->get_product();
							if ( ! $product ) {
								continue;
							}
							$sku = $product->get_sku();
							if ( $sku === $product_code ) {
								// Match found, save line item ID.
								$order_item->update_meta_data( 'zcrm_line_item_id', $line_item_id );
								$order_item->save();
								break;
							}
						}
					}
				}
			}

			$order->update_meta_data( $meta_key, $record_id );
			$order->save();
			$order->add_order_note( 'Zoho CRM ' . $module_name . ' synced successfully with ID: ' . $record_id );
			return;
		}
		// fclose( $fd );
	}

	/**
	 * Finds or creates a contact in Zoho CRM for the given order.
	 *
	 * First checks if the contact id is already stored in the order meta or the user meta.
	 * If not, it searches for a contact by email and, if found, saves the contact id.
	 * If no contact is found, it creates a new contact in Zoho CRM and saves the contact id.
	 *
	 * @param WC_Order $order The order object.
	 * @return int|string|WP_Error The contact ID in Zoho CRM, or an error object if the contact can't be created or found.
	 */
	protected function get_or_resolve_contact_id( $order ) {
		$contact_id = $order->get_customer_id()
			? get_user_meta( $order->get_customer_id(), 'zcrm_contact_id', true )
			: $order->get_meta( 'zcrm_contact_id', true );

		if ( $contact_id ) {
			return $contact_id;
		}

		$contact_id = $this->find_contact_id_by_email( $order->get_billing_email() );

		if ( ! is_wp_error( $contact_id ) && $contact_id ) {
			if ( $order->get_customer_id() ) {
				update_user_meta( $order->get_customer_id(), 'zcrm_contact_id', $contact_id );
			} else {
				$order->update_meta_data( 'zcrm_contact_id', $contact_id );
				$order->save();
			}
		} elseif ( is_wp_error( $contact_id ) ) {
			return $contact_id;
		}

		if ( empty( $contact_id ) ) {
			$contact_id   = new CMBIRD_ZCRM_Modules();
			$contact_data = array(
				'data' => array(
					array(
						'Contact_Name' => $order->get_billing_first_name() . ' ' . $order->get_billing_last_name(),
						'Email'        => $order->get_billing_email(),
						'Phone'        => $order->get_billing_phone(),
						'First_Name'   => $order->get_billing_first_name(),
						'Last_Name'    => $order->get_billing_last_name(),
						'Source'       => $order->get_meta( '_wc_order_attribution_utm_source', true ),
					),
				),
			);
			$response     = $contact_id->cmbird_create_record( 'Contacts', $contact_data );
			if ( is_wp_error( $response ) || empty( $response->data[0]->details->id ) ) {
				return new \WP_Error( 'zcrm_no_contact', 'Failed to create contact in Zoho CRM: ' . ( $response->get_error_message() ?? 'Unknown error' ) );
			}
			$contact_id = $response->data[0]->details->id;
			if ( $order->get_customer_id() ) {
				update_user_meta( $order->get_customer_id(), 'zcrm_contact_id', $contact_id );
			} else {
				$order->update_meta_data( 'zcrm_contact_id', $contact_id );
				$order->save();
			}
		}

		return $contact_id;
	}

	/**
	 * Finds or creates an account in Zoho CRM for the given order.
	 *
	 * @param WC_Order $order The order object.
	 * @return int|string|WP_Error The account ID in Zoho CRM, or an error object if the account can't be created or found.
	 */
	protected function get_or_resolve_account_id( $order ) {
		if ( ! $order->get_billing_company() ) {
			return null;
		}

		$account_id = $order->get_customer_id()
			? get_user_meta( $order->get_customer_id(), 'zcrm_account_id', true )
			: $order->get_meta( 'zcrm_account_id', true );

		if ( $account_id ) {
			return $account_id;
		}

		$account_id = $this->find_account_id_by_name( $order->get_billing_company() );

		if ( is_wp_error( $account_id ) ) {
			return $account_id;
		}

		if ( $account_id ) {
			if ( $order->get_customer_id() ) {
				update_user_meta( $order->get_customer_id(), 'zcrm_account_id', $account_id );
			} else {
				$order->update_meta_data( 'zcrm_account_id', $account_id );
				$order->save();
			}
		}
		// if empty, create a new account.
		if ( empty( $account_id ) ) {
			$account_data = array(
				'data' => array(
					array(
						'Account_Name'     => $order->get_billing_company(),
						'Phone'            => $order->get_billing_phone(),
						'Website'          => $order->get_billing_address_1(),
						'Billing_Street'   => $order->get_billing_address_1(),
						'Billing_City'     => $order->get_billing_city(),
						'Billing_State'    => $order->get_billing_state(),
						'Billing_Country'  => $order->get_billing_country(),
						'Billing_Code'     => $order->get_billing_postcode(),
						'Shipping_Street'  => $order->get_shipping_address_1(),
						'Shipping_City'    => $order->get_shipping_city(),
						'Shipping_State'   => $order->get_shipping_state(),
						'Shipping_Country' => $order->get_shipping_country(),
						'Shipping_Code'    => $order->get_shipping_postcode(),
					),
				),
			);
			$response     = $this->zcrm_modules->cmbird_create_record( 'Accounts', $account_data );
			if ( is_wp_error( $response ) || empty( $response->data[0]->details->id ) ) {
				return new \WP_Error( 'zcrm_no_account', 'Failed to create account in Zoho CRM: ' . ( $response->get_error_message() ?? 'Unknown error' ) );
			}
			$account_id = $response->data[0]->details->id;
			if ( $order->get_customer_id() ) {
				update_user_meta( $order->get_customer_id(), 'zcrm_account_id', $account_id );
			} else {
				$order->update_meta_data( 'zcrm_account_id', $account_id );
				$order->save();
			}
		}

		return $account_id;
	}

	/**
	 * Find Zoho contact ID by email
	 *
	 * @param string $email Contact email address.
	 * @return string|WP_Error Zoho contact ID if found, WP Error object otherwise
	 */
	protected function find_contact_id_by_email( $email ) {
		$url      = $this->zoho_crm_url . 'crm/v7/Contacts/search?email=' . rawurlencode( $email );
		$api      = new \CMBIRD_API_Handler_Zoho();
		$response = $api->execute_curl_call_get( $url );

		if ( is_wp_error( $response ) ) {
			return $response;
		}

		return ! empty( $response->data[0]->id ) ? $response->data[0]->id : '';
	}

	/**
	 * Find Zoho account by name
	 *
	 * @param string $name Account name.
	 * @return string | WP_Error Zoho account ID if found, Error object otherwise.
	 */
	protected function find_account_id_by_name( $name ) {
		$url      = $this->zoho_crm_url . 'crm/v7/Accounts/search?word=' . rawurlencode( $name );
		$api      = new \CMBIRD_API_Handler_Zoho();
		$response = $api->execute_curl_call_get( $url );

		if ( is_wp_error( $response ) ) {
			return $response;
		}

		return ! empty( $response->data[0]->id ) ? $response->data[0]->id : '';
	}

	/**
	 * Format order for Zoho CRM
	 *
	 * @param object $order Order object.
	 * @param string $contact_id Zoho contact ID.
	 * @param string $account_id Zoho account ID.
	 * @param bool   $update Whether this is an update operation.
	 * @return array
	 */
	protected function format_order_for_zoho( $order, $contact_id, $account_id, $update = false ) {
		$ordered_items = array();

		foreach ( $order->get_items() as $item ) {
			$product         = $item->get_product();
			$zcrm_product_id = $this->zcrm_product->get_zoho_product_id( $product, $order );

			if ( ! $zcrm_product_id ) {
				continue;
			}

			// Ensure the product in Zoho has all available tax rates before processing order.
			$this->zcrm_product->update_zoho_product_with_tax_rates( $product, $zcrm_product_id, $order );

			$line_item_id = '';
			if ( $update ) {
				$existing_line_item_id = $item->get_meta( 'zcrm_line_item_id', true );
				if ( ! empty( $existing_line_item_id ) ) {
					$line_item_id = $existing_line_item_id;
				}
			}

			$zoho_tax = $this->get_zoho_tax_data_for_item( $item );

			// Calculate unit price based on WooCommerce tax settings.
			$unit_price = $this->get_item_unit_price( $item );

			$ordered_items[] = array(
				'Product_Name' => array(
					'name' => $item->get_name(),
					'id'   => $zcrm_product_id,
				),
				'Quantity'     => $item->get_quantity(),
				'List_Price'   => round( $unit_price, 2 ),
				'id'           => $line_item_id,
				'Line_Tax'     => $zoho_tax ? array( $zoho_tax ) : array(),
				'Taxable'      => $zoho_tax ? true : false, // Set Taxable to false if no tax mapping is found.
			);
		}
		if ( empty( $ordered_items ) ) {
			return array( 'data' => array() ); // No items to process.
		}
		$custom_fields = $this->get_custom_mapped_fields_from_order( $order );

		// Merge with core payload.
		$sales_order = array(
			'Contact_Name'     => array( 'id' => $contact_id ),
			'Account_Name'     => $account_id ? array( 'id' => $account_id ) : null,
			'Subject'          => 'WC-' . $order->get_id(),
			'Billing_Street'   => $order->get_billing_address_1(),
			'Billing_City'     => $order->get_billing_city(),
			'Billing_State'    => $order->get_billing_state(),
			'Billing_Country'  => $order->get_billing_country(),
			'Billing_Code'     => $order->get_billing_postcode(),
			'Shipping_Street'  => $order->get_shipping_address_1(),
			'Shipping_City'    => $order->get_shipping_city(),
			'Shipping_State'   => $order->get_shipping_state(),
			'Shipping_Country' => $order->get_shipping_country(),
			'Shipping_Code'    => $order->get_shipping_postcode(),
			'Currency'         => $order->get_currency(),
			// 'Discount' => floatval( $order->get_discount_total() ),.
			'Shipping'         => round( floatval( $order->get_shipping_total() + $order->get_shipping_tax() ), 2 ),
			'Adjustment'       => round( floatval( $order->get_total_fees() ), 2 ),
			'Status'           => 'Approved',
			'Ordered_Items'    => $ordered_items,
		);

		// Add layout ID if selected.
		$selected_layout = get_option( 'zcrm_sales_order_layout', '' );
		if ( ! empty( $selected_layout ) ) {
			$sales_order['Layout'] = array( 'id' => $selected_layout );
		}
		// if its an update, then remove currency field.
		if ( $update && isset( $sales_order['Currency'] ) ) {
			unset( $sales_order['Currency'] );
		}

		// Merge mapped fields.
		$sales_order = array_merge( $sales_order, $custom_fields );

		return array( 'data' => array( $sales_order ) );
	}

	/**
	 * Get Zoho tax data for a given order item.
	 * This method handles both tax-inclusive and tax-exclusive pricing by:
	 * 1. First checking actual order item taxes (most accurate for the specific order)
	 * 2. Falling back to product tax class rates if item taxes are not available
	 * 3. Supporting both mapped Zoho tax rates and WooCommerce native rates
	 *
	 * @param WC_Order_Item_Product $item Order item.
	 * @return array|null
	 */
	protected function get_zoho_tax_data_for_item( $item ) {
		$product = $item->get_product();
		if ( ! $product ) {
			return null;
		}

		// First, try to get tax from the actual order item taxes (most accurate).
		$taxes = $item->get_taxes();
		if ( ! empty( $taxes['total'] ) ) {
			foreach ( $taxes['total'] as $rate_id => $tax_amount ) {
				if ( $tax_amount > 0 ) {
					$rate_code = WC_Tax::get_rate_code( $rate_id );
					$mapped    = $this->zcrm_product->get_zoho_tax_by_woo_tax_code( $rate_code );

					if ( $mapped && isset( $mapped['id'] ) && ! empty( $mapped['id'] ) ) {
						$tax_name       = isset( $mapped['name'] ) && ! empty( $mapped['name'] ) ? $mapped['name'] : 'Standard';
						$tax_percentage = isset( $mapped['value'] ) ? floatval( $mapped['value'] ) : 0;

						// If no mapped percentage, calculate from WooCommerce tax rate.
						if ( $tax_percentage <= 0 ) {
							$wc_tax_rate    = WC_Tax::get_rate_percent_value( $rate_id );
							$tax_percentage = floatval( $wc_tax_rate );
						}

						// Ensure we have a valid tax percentage.
						if ( $tax_percentage > 0 && $tax_percentage <= 100 ) {
							return array(
								'name'       => $tax_name,
								'percentage' => $tax_percentage,
							);
						}
					}
				}
			}
		}

		// Fallback: Get tax rates for this product's tax class.
		$tax_class = $product->get_tax_class();
		$tax_rates = WC_Tax::get_rates_for_tax_class( $tax_class );

		if ( empty( $tax_rates ) ) {
			return null;
		}

		// Get the first applicable tax rate.
		$rate_data = reset( $tax_rates );
		$rate_id   = key( $tax_rates );

		if ( ! $rate_data || ! $rate_id ) {
			return null;
		}

		// Get the rate code and find mapped Zoho tax.
		$rate_code = WC_Tax::get_rate_code( $rate_id );
		$mapped    = $this->zcrm_product->get_zoho_tax_by_woo_tax_code( $rate_code );

		if ( ! $mapped || ! isset( $mapped['id'] ) || empty( $mapped['id'] ) ) {
			return null;
		}

		$tax_name       = isset( $mapped['name'] ) && ! empty( $mapped['name'] ) ? $mapped['name'] : 'Standard';
		$tax_percentage = isset( $mapped['value'] ) ? floatval( $mapped['value'] ) : floatval( $rate_data['rate'] );

		// Ensure we have a valid tax percentage (between 0 and 100).
		if ( $tax_percentage > 0 && $tax_percentage <= 100 ) {
			return array(
				'name'       => $tax_name,
				'percentage' => $tax_percentage,
			);
		}

		return null;
	}

	/**
	 * Get the correct unit price for an item based on WooCommerce tax settings.
	 * For Zoho CRM, we ALWAYS need to send the price EXCLUDING tax in the List_Price field,
	 * because Zoho CRM will apply the tax percentage on top of the List_Price.
	 * This ensures accurate tax calculations regardless of WooCommerce tax settings.
	 *
	 * @param WC_Order_Item_Product $item Order item.
	 * @return float
	 */
	protected function get_item_unit_price( $item ) {
		$quantity = $item->get_quantity();

		if ( $quantity <= 0 ) {
			return 0;
		}

		// For Zoho CRM, we always need the price EXCLUDING tax.
		// because Zoho will apply the tax percentage on top of the List_Price.
		return round( floatval( $item->get_subtotal() / $quantity ), 2 );
	}

	/**
	 * Get custom mapped fields from order meta
	 *
	 * @param WC_Order $order Order object.
	 * @return array
	 */
	protected function get_custom_mapped_fields_from_order( $order ) {
		$mapped_fields_json = get_option( 'zcrm_sales_orders_custom_fields' );
		if ( empty( $mapped_fields_json ) ) {
			return array();
		}

		$mapped_fields = json_decode( $mapped_fields_json, true );
		if ( ! is_array( $mapped_fields ) ) {
			return array();
		}

		// get all custom fields for Sales Orders.
		if ( ! empty( $this->zcrm_custom_fields ) ) {
			$custom_fields = $this->zcrm_custom_fields;
		}

		$zoho_fields = array();

		foreach ( $mapped_fields as $woo_meta_key => $zoho_field_api_name ) {
			$value = $order->get_meta( $woo_meta_key, true );

			if ( ! empty( $value ) ) {
				// Use Zoho CRM field api name as key in payload.
				$zoho_fields[ $zoho_field_api_name ] = $value;
			}
		}

		return $zoho_fields;
	}

	/**
	 * Format order data for the specified Zoho CRM module
	 *
	 * @param object $order WC_Order object.
	 * @param string $contact_id Zoho contact ID.
	 * @param string $account_id Zoho account ID.
	 * @param string $module_name Zoho CRM module name.
	 * @param bool   $update Whether this is an update operation.
	 * @return array
	 */
	protected function format_order_for_module( $order, $contact_id, $account_id, $module_name, $update = false ) {
		if ( 'Deals' === $module_name ) {
			return $this->format_order_for_deals( $order, $contact_id, $account_id, $update );
		} else {
			return $this->format_order_for_zoho( $order, $contact_id, $account_id, $update );
		}
	}

	/**
	 * Format order data for Zoho CRM Deals module using field mapping
	 *
	 * @param object $order WC_Order object.
	 * @param string $contact_id Zoho contact ID.
	 * @param string $account_id Zoho account ID.
	 * @param bool   $update Whether this is an update operation.
	 * @return array
	 */
	protected function format_order_for_deals( $order, $contact_id, $account_id, $update = false ) {
		// Get field mapping from WordPress options.
		$field_mapping = get_option( 'cmbird_zcrm_deal_field_mapping', array() );

		// Base deal data with hardcoded fields.
		$deal_data = array(
			'Deal_Name'    => 'WC-' . $order->get_id(),  // Hardcoded as Deal_Name.
			'Amount'       => round( floatval( $order->get_total() ), 2 ), // Hardcoded as Amount.
			'Currency'     => $order->get_currency(),        // Hardcoded as Currency.
			'Contact_Name' => array( 'id' => $contact_id ),
		);

		// Add Account if available.
		if ( $account_id ) {
			$deal_data['Account_Name'] = array( 'id' => $account_id );
		}

		// Add Stage based on order status mapping.
		$order_status       = $order->get_status();
		$status_with_prefix = 'wc-' . $order_status; // WooCommerce statuses are stored with 'wc-' prefix.
		$stage_mapping      = get_option( 'cmbird_zcrm_order_status_stage_mapping', array() );

		if ( ! empty( $stage_mapping[ $status_with_prefix ] ) ) {
			$deal_data['Stage'] = $stage_mapping[ $status_with_prefix ];
		}

		// Apply dynamic field mappings from user configuration.
		if ( ! empty( $field_mapping ) && is_array( $field_mapping ) ) {
			foreach ( $field_mapping as $mapping ) {
				if ( empty( $mapping['key'] ) || empty( $mapping['value'] ) ) {
					continue;
				}

				$woo_field  = $mapping['key'];
				$zoho_field = $mapping['value'];

				// Get WooCommerce field value based on the key.
				$field_value = $this->get_woo_order_field_value( $order, $woo_field );

				if ( null !== $field_value ) {
					$deal_data[ $zoho_field ] = $field_value;
				}
			}
		}

		// Add layout ID if selected for deals.
		$selected_layout = get_option( 'zcrm_deals_layout', '' );
		if ( ! empty( $selected_layout ) ) {
			$deal_data['Layout'] = array( 'id' => $selected_layout );
		}

		return array( 'data' => array( $deal_data ) );
	}

	/**
	 * Returns the value of the specified WooCommerce order field.
	 *
	 * @param WC_Order $order Order object.
	 * @param string   $field_key The key of the field to retrieve.
	 *
	 * @return string|null The value of the specified field. Null if the field is not supported.
	 */
	private function get_woo_order_field_value( $order, $field_key ) {
		switch ( $field_key ) {
			case 'billing_first_name':
				return $order->get_billing_first_name();
			case 'billing_last_name':
				return $order->get_billing_last_name();
			case 'billing_company':
				return $order->get_billing_company();
			case 'billing_address_1':
				return $order->get_billing_address_1();
			case 'billing_address_2':
				return $order->get_billing_address_2();
			case 'billing_city':
				return $order->get_billing_city();
			case 'billing_state':
				return $order->get_billing_state();
			case 'billing_postcode':
				return $order->get_billing_postcode();
			case 'billing_country':
				return $order->get_billing_country();
			case 'billing_email':
				return $order->get_billing_email();
			case 'billing_phone':
				return $order->get_billing_phone();
			case 'shipping_first_name':
				return $order->get_shipping_first_name();
			case 'shipping_last_name':
				return $order->get_shipping_last_name();
			case 'shipping_company':
				return $order->get_shipping_company();
			case 'shipping_address_1':
				return $order->get_shipping_address_1();
			case 'shipping_address_2':
				return $order->get_shipping_address_2();
			case 'shipping_city':
				return $order->get_shipping_city();
			case 'shipping_state':
				return $order->get_shipping_state();
			case 'shipping_postcode':
				return $order->get_shipping_postcode();
			case 'shipping_country':
				return $order->get_shipping_country();
			case 'order_date':
				return $order->get_date_created()->format( 'Y-m-d' );
			case 'payment_method':
				return $order->get_payment_method();
			case 'payment_method_title':
				return $order->get_payment_method_title();
			case 'shipping_method':
				$shipping_methods = array();
				foreach ( $order->get_shipping_methods() as $shipping_method ) {
					$shipping_methods[] = $shipping_method->get_method_title();
				}
				return implode( ', ', $shipping_methods );
			case 'shipping_total':
				return round( floatval( $order->get_shipping_total() ), 2 );
			case 'tax_total':
				return round( floatval( $order->get_total_tax() ), 2 );
			case 'discount_total':
				return round( floatval( $order->get_discount_total() ), 2 );
			case 'customer_note':
				return $order->get_customer_note();
			case 'total_weight':
				$total_weight = 0;
				foreach ( $order->get_items() as $item ) {
					$product = $item->get_product();
					if ( $product && $product->get_weight() ) {
						$total_weight += floatval( $product->get_weight() ) * $item->get_quantity();
					}
				}
				return round( $total_weight, 2 );
			case 'item_count':
				return $order->get_item_count();
			case 'products':
				$product_names = array();
				foreach ( $order->get_items() as $item ) {
					$product_names[] = $item->get_name();
				}
				return implode( ', ', $product_names );
			default:
				return null;
		}
	}
}
$CMBIRD_ZCRM_SalesOrder = new CMBIRD_ZCRM_SalesOrder();
