<?php
/**
 * Message Parser Class.
 *
 * Supports placeholders for both WooCommerce orders and WordPress user data (e.g. user login/signup).
 * Custom meta fields are also supported.
 *
 * USAGE:
 *   In your templates or messages, use {{placeholder_name}} to dynamically replace with order/user/site info.
 *
 * FULL PLACEHOLDER LIST:
 *
 * 1. GENERAL (always applies):
 *   {{sitename}}          -> get_bloginfo('name') [Site Title]
 *   {{siteurl}}           -> home_url() [Home URL of the site]
 *   {{wordpress-url}}     -> site_url() [WordPress install URL]
 *   {{tagline}}           -> get_bloginfo('description') [Site Tagline]
 *   {{privacy-policy}}    -> get_privacy_policy_url() [Privacy Policy Page URL]
 *
 * 2. WordPress USER (If no WC order, but user info is present):
 *   - Original / Legacy:
 *     {{user_name}}            -> user->user_login [Username]
 *     {{user_first_last_name}} -> user_meta('first_name' + 'last_name') [Full Name]
 *     {{wc_billing_first_name}}-> user_meta('billing_first_name') [Billing First Name]
 *     {{wc_billing_last_name}} -> user_meta('billing_last_name') [Billing Last Name]
 *     {{wc_billing_phone}}     -> user_meta('billing_phone') [Billing Phone]
 *     {{shop_name}}            -> get_bloginfo('name') [Site Title]
 *     {{current_date_time}}    -> Carbon::now() [Current Server Date/Time]
 *     {{site_link}}            -> site_url() [Site URL]
 *     {{customer_note}}        -> base_replacement [Custom context note]
 *
 *   - New (wp- prefix):
 *     {{wp-first-name}}   -> user_meta('first_name') [User First Name]
 *     {{wp-last-name}}    -> user_meta('last_name') [User Last Name]
 *     {{wp-username}}     -> user->user_login [Username]
 *     {{wp-nickname}}     -> user_meta('nickname') [User Nickname]
 *     {{wp-display-name}} -> user->display_name [User Display Name]
 *     {{wp-email}}        -> user->user_email [User Email Address]
 *     {{wp-user-website}} -> user->user_url [User Website URL]
 *     {{wp-user-bio}}     -> user->description [User Bio / Description]
 *
 *   - Custom User Meta:
 *     e.g. {{meta_key}} -> get_user_meta($user->ID, 'meta_key', true) [Value from Database]
 *
 * 3. WOOCOMMERCE ORDER (If an order object is present):
 *   Used in Order Status changes, New Order alerts, Refunds, and any WooCommerce-triggered actions.
 *
 *   - Custom Order Meta:
 *     e.g. {{my_meta}} -> $order->get_meta('my_meta') [Value from Order Meta / Custom Fields]
 *
 *   - Legacy / Original (Common):
 *     {{id}}                    -> $order->get_id() [Order ID]
 *     {{order_key}}             -> $order->get_order_key() [Unique Order Key]
 *     {{order_date}}            -> $order->get_date_created() [Formatted Order Date]
 *     {{order_link}}            -> WC View Order URL [Link with order key]
 *     {{order_total}}           -> $order->get_total() [Grand Total]
 *     {{order_subtotal}}        -> $order->get_subtotal() [Order Subtotal]
 *     {{order_discount}}        -> $order->get_total_discount() [Total Discount Amount]
 *     {{order_tax}}             -> $order->get_total_tax() [Total Tax Amount]
 *     {{order_shipping}}        -> $order->get_shipping_total() [Shipping Cost]
 *     {{order_shipping_tax}}    -> $order->get_shipping_tax() [Shipping Tax Amount]
 *     {{status}}                -> $order->get_status() [Current Order Status]
 *     {{currency}}              -> get_woocommerce_currency_symbol() [Currency Symbol]
 *     {{payment_method}}        -> $order->get_payment_method() [Payment Method Slug]
 *     {{payment_method_title}}  -> $order->get_payment_method_title() [Payment Method Name]
 *     {{transaction_id}}        -> $order->get_transaction_id() [Payment Transaction ID]
 *     {{bacs_account}}          -> woocommerce_bacs_accounts [Bank Transfer Details]
 *     {{shop_name}}             -> get_bloginfo('name') [Site Title]
 *     {{cust_note}}             -> $order->get_customer_note() [Customer Note]
 *     {{product}}               -> Order Items Summary [Detailed list with Qty and Prices]
 *     {{product_name}}          -> $item->get_name() [Comma-separated Product Titles]
 *     {{unique_transfer_code}}  -> _unique_transfer_code [Custom Transfer Code]
 *
 *   - Billing & Shipping (Legacy):
 *     {{billing_first_name}}     -> Billing First Name
 *     {{billing_last_name}}      -> Billing Last Name
 *     {{billing_company}}        -> Billing Company
 *     {{billing_address_1}}      -> Billing Address Line 1
 *     {{billing_address_2}}      -> Billing Address Line 2
 *     {{billing_city}}           -> Billing City
 *     {{billing_postcode}}       -> Billing Postcode
 *     {{billing_country}}        -> Billing Country
 *     {{billing_state}}          -> Billing State
 *     {{billing_email}}          -> Billing Email
 *     {{billing_phone}}          -> Billing Phone
 *     {{shipping_first_name}}    -> Shipping First Name
 *     {{shipping_last_name}}     -> Shipping Last Name
 *     {{shipping_company}}       -> Shipping Company
 *     {{shipping_address_1}}     -> Shipping Address Line 1
 *     {{shipping_address_2}}     -> Shipping Address Line 2
 *     {{shipping_city}}          -> Shipping City
 *     {{shipping_postcode}}      -> Shipping Postcode
 *     {{shipping_country}}       -> Shipping Country
 *     {{shipping_state}}         -> Shipping State
 *     {{shipping_method}}        -> Shipping Method Slug
 *     {{shipping_method_title}}  -> Shipping Method Name
 *
 *   - Additional WooCommerce (wc- prefix):
 *     Used for smart formatting (New-lines, Lists, Links). Ideal for professional summaries.
 *     {{wc-order}}              -> $order->get_order_number() [Order Number]
 *     {{wc-order-id}}           -> $order->get_id() [Order ID]
 *     {{wc-order-status}}       -> $order->get_status() [Order Status]
 *     {{wc-order-date}}         -> $order->get_date_created() [Formatted Order Date]
 *     {{wc-product-names}}      -> Product titles [Comma-separated Names]
 *     {{wc-product-names-br}}   -> Product titles [New-line separated Names]
 *     {{wc-product-name-count}} -> Summary [e.g. 'Product A and 2 more']
 *     {{wc-product-link}}       -> Product URLs [Comma-separated permalinks]
 *     {{wc-product-link-br}}    -> Product URLs [New-line separated permalinks]
 *     {{wc-product-name-link}}  -> Title (URL) [Comma-separated Name + URL]
 *     {{wc-product-name-link-br}} -> Title (URL) [New-line separated Name + URL]
 *     {{wc-total-products}}     -> Unique product count [Number of unique items in order]
 *     {{wc-total-items}}        -> Total item quantity [Sum of all item quantities]
 *     {{wc-order-items}}        -> Detailed list [Name x Qty]
 *     {{wc-order-items-br}}     -> Detailed list [Name x Qty (New-line)]
 *     {{wc-order-items-price}}  -> Full summary [Name x Qty - Price]
 *     {{wc-sku}}                -> Product SKUs [Comma-separated SKUs]
 *     {{wc-sku-br}}             -> Product SKUs [New-line separated SKUs]
 *     {{wc-order-amount}}       -> $order->get_total() [Grand Total]
 *     {{wc-discount}}           -> $order->get_total_discount() [Discount Amount]
 *     {{wc-tax}}                -> $order->get_total_tax() [Tax Amount]
 *     {{wc-order-amount-ex-tax}}-> Total - Tax [Net Order Amount]
 *     {{wc-payment-method}}     -> $order->get_payment_method() [Payment Method ID]
 *     {{wc-shipping-method}}    -> $order->get_shipping_method() [Shipping Method Name]
 *     {{wc-shipping-cost}}      -> $order->get_shipping_total() [Shipping Amount]
 *     {{wc-refund-amount}}      -> $order->get_total_refunded() [Total Refunded]
 *     {{wc-refund-reason}}      -> Refund reasons [Comma-separated reasons]
 *     {{wc-order-notes}}        -> $order->get_customer_note() [Customer Note]
 *
 *   - WooCommerce Billing/Shipping (hyphen versions):
 *     Alternative naming convention for easier integration and consistency.
 *     {{wc-billing-first-name}}  -> $order->get_billing_first_name() [First Name]
 *     {{wc-billing-last-name}}   -> $order->get_billing_last_name() [Last Name]
 *     {{wc-billing-email}}       -> $order->get_billing_email() [Email Address]
 *     {{wc-billing-phone}}       -> $order->get_billing_phone() [Phone Number]
 *     {{wc-billing-address-line-1}} -> $order->get_billing_address_1() [Address Line 1]
 *     {{wc-billing-address-line-2}} -> $order->get_billing_address_2() [Address Line 2]
 *     {{wc-billing-city}}        -> $order->get_billing_city() [City]
 *     {{wc-billing-postcode}}    -> $order->get_billing_postcode() [Postcode]
 *     {{wc-billing-state}}       -> $order->get_billing_state() [State]
 *     {{wc-billing-country}}     -> $order->get_billing_country() [Country Code]
 *     {{wc-shipping-first-name}} -> $order->get_shipping_first_name() [First Name]
 *     {{wc-shipping-last-name}}  -> $order->get_shipping_last_name() [Last Name]
 *     {{wc-shipping-address-line-1}} -> $order->get_shipping_address_1() [Shipping Address 1]
 *     {{wc-shipping-city}}       -> $order->get_shipping_city() [Shipping City]
 *
 * @package automation-web-platform
 */

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

/**
 * Class WAWP_Message_Parser
 * Handles parsing of message placeholders for WooCommerce and WordPress.
 */
class WAWP_Message_Parser {

	/**
	 * Parse message placeholders.
	 *
	 * @param string $msg Message template.
	 * @param array  $base_replacements Base replacements.
	 * @param int    $order_id Order ID.
	 * @param int    $user_id User ID.
	 * @return string Parsed message.
	 */
	public static function parse_message_placeholders( $msg, $base_replacements, $order_id, $user_id ) {
		$wawp_wa = array(
			'id',
			'order_key',
			'billing_first_name',
			'billing_last_name',
			'billing_company',
			'billing_address_1',
			'billing_address_2',
			'billing_city',
			'billing_postcode',
			'billing_country',
			'billing_state',
			'billing_email',
			'billing_phone',
			'shipping_first_name',
			'shipping_last_name',
			'shipping_company',
			'shipping_address_1',
			'shipping_address_2',
			'shipping_city',
			'shipping_postcode',
			'shipping_country',
			'shipping_state',
			'shipping_method',
			'shipping_method_title',
			'bacs_account',
			'payment_method',
			'payment_method_title',
			'order_subtotal',
			'order_discount',
			'cart_discount',
			'order_tax',
			'order_shipping',
			'order_shipping_tax',
			'order_total',
			'status',
			'shop_name',
			'currency',
			'cust_note',
			'note',
			'product',
			'product_name',
			'dpd',
			'unique_transfer_code',
			'order_date',
			'order_link',
			'transaction_id',
			'current_date_time',
			'user_name',
			'user_first_last_name',
			'wc_billing_first_name',
			'wc_billing_last_name',
			'wc_billing_phone',
			'site_link',
			'customer_note',
		);

		$order = null;
		$user  = null;

		if ( $order_id ) {
			$order = function_exists( 'wc_get_order' ) ? wc_get_order( $order_id ) : null;
		}
		if ( $user_id ) {
			$user = get_userdata( $user_id );
		}

		// Replace any "base replacements" first.
		if ( is_array( $base_replacements ) ) {
			foreach ( $base_replacements as $k => $v ) {
				$inner_key = trim( $k, '{}' );
				if ( ! empty( $inner_key ) ) {
					// Replace double braces first to avoid leaving outer braces.
					$msg = str_replace( '{{' . $inner_key . '}}', $v, $msg );
					// Then replace single braces.
					$msg = str_replace( '{' . $inner_key . '}', $v, $msg );
				}
				// Finally replace exact original key.
				$msg = str_replace( $k, $v, $msg );
			}
		}

		// Determine symbols and locale.
		$currency_symb = ( class_exists( 'WooCommerce' ) && function_exists( 'get_woocommerce_currency_symbol' ) )
			? html_entity_decode( get_woocommerce_currency_symbol() )
			: '';

		// Use regex to find all placeholders in double braces.
		preg_match_all( '/{{(.*?)}}/', $msg, $search );
		$locale    = get_locale();
		$is_arabic = ( strpos( $locale, 'ar' ) === 0 );

		foreach ( $search[1] as $variable ) {
			$var_lower = strtolower( $variable );

			// --------------------------------------------------------------
			// 1) Handle "General" placeholders that always apply.
			// --------------------------------------------------------------
			if ( in_array( $var_lower, array( 'sitename', 'siteurl', 'wordpress-url', 'tagline', 'privacy-policy', 'wawp_greeting_casual', 'wawp_greeting_formal', 'wawp_greeting_english' ), true ) ) {
				switch ( $var_lower ) {
					case 'sitename':
						$msg = str_replace( '{{' . $variable . '}}', get_bloginfo( 'name' ), $msg );
						break;
					case 'siteurl':
						$msg = str_replace( '{{' . $variable . '}}', home_url(), $msg );
						break;
					case 'wordpress-url':
						$msg = str_replace( '{{' . $variable . '}}', site_url(), $msg );
						break;
					case 'tagline':
						$msg = str_replace( '{{' . $variable . '}}', get_bloginfo( 'description' ), $msg );
						break;
					case 'privacy-policy':
						$pp_url = function_exists( 'get_privacy_policy_url' ) ? get_privacy_policy_url() : '';
						$msg    = str_replace( '{{' . $variable . '}}', $pp_url ? $pp_url : '', $msg );
						break;
					case 'wawp_greeting_casual':
						$casual = array( 'أهلاً بك', 'يا هلا وغلا', 'مرحباً بك', 'مرحباً', 'يا هلا' );
						$msg    = str_replace( '{{' . $variable . '}}', $casual[ array_rand( $casual ) ], $msg );
						break;
					case 'wawp_greeting_formal':
						$formal = array( 'السلام عليكم ورحمة الله وبركاته', 'تحية طيبة وبعد،', 'السلام عليكم ورحمة الله', 'مرحباً بك عميلنا العزيز' );
						$msg    = str_replace( '{{' . $variable . '}}', $formal[ array_rand( $formal ) ], $msg );
						break;
					case 'wawp_greeting_english':
						$english = array( 'Hello!', 'Hi there!', 'Greetings!', 'Welcome!' );
						$msg     = str_replace( '{{' . $variable . '}}', $english[ array_rand( $english ) ], $msg );
						break;
				}
				continue;
			}

			// --------------------------------------------------------------
			// 2) If NO WooCommerce Order but we DO have a WP user.
			// --------------------------------------------------------------
			if ( ! $order && $user ) {
				switch ( $var_lower ) {
					case 'user_name':
						$msg = str_replace( '{{' . $variable . '}}', $user->user_login, $msg );
						break;
					case 'user_first_last_name':
						$fn  = get_user_meta( $user->ID, 'first_name', true );
						$ln  = get_user_meta( $user->ID, 'last_name', true );
						$nm  = trim( $fn . ' ' . $ln );
						$msg = str_replace( '{{' . $variable . '}}', $nm, $msg );
						break;
					case 'wc_billing_first_name':
					case 'wc_billing_last_name':
					case 'wc_billing_phone':
						$val = get_user_meta( $user->ID, str_replace( 'wc_', '', $var_lower ), true );
						$msg = str_replace( '{{' . $variable . '}}', $val ? $val : 'N/A', $msg );
						break;
					case 'shop_name':
						$msg = str_replace( '{{' . $variable . '}}', get_bloginfo( 'name' ), $msg );
						break;
					case 'current_date_time':
						$formatted = wp_date( 'Y-m-d H:i:s' );
						$msg       = str_replace( '{{' . $variable . '}}', $formatted, $msg );
						break;
					case 'site_link':
						$msg = str_replace( '{{' . $variable . '}}', site_url(), $msg );
						break;
					case 'customer_note':
						$val = isset( $base_replacements['{customer_note}'] ) ? $base_replacements['{customer_note}'] : 'N/A';
						$msg = str_replace( '{{' . $variable . '}}', $val, $msg );
						break;

					// New WP placeholders.
					case 'wp-first-name':
						$val = get_user_meta( $user->ID, 'first_name', true );
						$msg = str_replace( '{{' . $variable . '}}', $val ? $val : 'N/A', $msg );
						break;
					case 'wp-last-name':
						$val = get_user_meta( $user->ID, 'last_name', true );
						$msg = str_replace( '{{' . $variable . '}}', $val ? $val : 'N/A', $msg );
						break;
					case 'wp-username':
						$val = $user->user_login;
						$msg = str_replace( '{{' . $variable . '}}', $val ? $val : 'N/A', $msg );
						break;
					case 'wp-nickname':
						$val = get_user_meta( $user->ID, 'nickname', true );
						$msg = str_replace( '{{' . $variable . '}}', $val ? $val : 'N/A', $msg );
						break;
					case 'wp-display-name':
						$val = $user->display_name;
						$msg = str_replace( '{{' . $variable . '}}', $val ? $val : 'N/A', $msg );
						break;
					case 'wp-email':
						$val = $user->user_email;
						$msg = str_replace( '{{' . $variable . '}}', $val ? $val : 'N/A', $msg );
						break;
					case 'wp-user-website':
						$val = $user->user_url;
						$msg = str_replace( '{{' . $variable . '}}', $val ? $val : 'N/A', $msg );
						break;
					case 'wp-user-bio':
						$val = $user->description;
						$msg = str_replace( '{{' . $variable . '}}', $val ? $val : 'N/A', $msg );
						break;

					default:
						// Attempt to load from user meta for unknown placeholders.
						$val = get_user_meta( $user->ID, $var_lower, true );
						if ( ! $val ) {
							$val = 'N/A';
						}
						$msg = str_replace( '{{' . $variable . '}}', $val, $msg );
						break;
				}
			} elseif ( $order instanceof \WC_Order ) {
				// --------------------------------------------------------------
				// 3) If we DO have a WooCommerce order.
				// --------------------------------------------------------------
				// Load user from order if not already loaded.
				if ( ! $user && $order->get_user_id() ) {
					$user = get_userdata( $order->get_user_id() );
				}

				switch ( $var_lower ) {
					// Existing placeholders (unchanged).
					case 'id':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_id(), $msg );
						break;
					case 'order_date':
						$df    = get_option( 'date_format' );
						$tf    = get_option( 'time_format' );
						$od    = $order->get_date_created();
						$d_str = $od ? wp_date( "$df $tf", $od->getTimestamp() ) : '';
						$msg   = str_replace( '{{' . $variable . '}}', $d_str, $msg );
						break;
					case 'order_link':
						$url = wc_get_endpoint_url( 'order-received', $order->get_id(), wc_get_checkout_url() );
						$url = add_query_arg( 'key', $order->get_order_key(), $url );
						$msg = str_replace( '{{' . $variable . '}}', $url, $msg );
						break;
					case 'product':
						$items = '';
						$i     = 0;
						foreach ( $order->get_items() as $it ) {
							++$i;
							$nl     = ( $i > 1 ) ? "\n" : '';
							$p      = $it->get_product();
							$pn     = $p ? $p->get_name() : '';
							$qty    = $it->get_quantity();
							$tot    = $it->get_total();
							$items .= $nl . $i . '. ' . $pn . ' * (' . $qty . ') = ' . number_format( $tot, wc_get_price_decimals() ) . ' ' . $currency_symb;
						}
						$msg = str_replace( '{{' . $variable . '}}', html_entity_decode( $items ), $msg );
						break;
					case 'order_discount':
						$val = number_format( $order->get_total_discount(), wc_get_price_decimals() );
						$msg = str_replace( '{{' . $variable . '}}', $val, $msg );
						break;
					case 'product_name':
						$names = array();
						foreach ( $order->get_items() as $it ) {
							$prod = $it->get_product();
							if ( $prod ) {
								$names[] = $prod->get_name();
							}
						}
						$msg = str_replace( '{{' . $variable . '}}', implode( ', ', $names ), $msg );
						break;
					case 'cart_discount':
						$val = number_format( $order->get_discount_total(), wc_get_price_decimals() );
						$msg = str_replace( '{{' . $variable . '}}', $val, $msg );
						break;
					case 'order_subtotal':
						$val = number_format( $order->get_subtotal(), wc_get_price_decimals() );
						$msg = str_replace( '{{' . $variable . '}}', $val, $msg );
						break;
					case 'order_total':
						$val = number_format( $order->get_total(), wc_get_price_decimals() );
						$msg = str_replace( '{{' . $variable . '}}', $val, $msg );
						break;
					case 'status':
						$status_name = wc_get_order_status_name( $order->get_status() );
						$msg         = str_replace( '{{' . $variable . '}}', $status_name, $msg );
						break;
					case 'order_tax':
						$val = number_format( $order->get_total_tax(), wc_get_price_decimals() );
						$msg = str_replace( '{{' . $variable . '}}', $val, $msg );
						break;
					case 'order_discount':
						$val = number_format( $order->get_total_discount(), wc_get_price_decimals() );
						$msg = str_replace( '{{' . $variable . '}}', $val, $msg );
						break;
					case 'cart_discount':
						$val = number_format( $order->get_discount_total(), wc_get_price_decimals() );
						$msg = str_replace( '{{' . $variable . '}}', $val, $msg );
						break;
					case 'order_shipping':
						$val = number_format( $order->get_shipping_total(), wc_get_price_decimals() );
						$msg = str_replace( '{{' . $variable . '}}', $val, $msg );
						break;
					case 'order_shipping_tax':
						$val = number_format( $order->get_shipping_tax(), wc_get_price_decimals() );
						$msg = str_replace( '{{' . $variable . '}}', $val, $msg );
						break;
					case 'currency':
						$msg = str_replace( '{{' . $variable . '}}', $currency_symb, $msg );
						break;
					case 'shop_name':
						$msg = str_replace( '{{' . $variable . '}}', html_entity_decode( get_bloginfo( 'name' ) ), $msg );
						break;
					case 'cust_note':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_customer_note(), $msg );
						break;
					case 'shipping_method':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_shipping_method(), $msg );
						break;
					case 'order_shipping':
						$val = number_format( $order->get_shipping_total(), wc_get_price_decimals() );
						$msg = str_replace( '{{' . $variable . '}}', $val, $msg );
						break;
					case 'order_shipping_tax':
						$val = number_format( $order->get_shipping_tax(), wc_get_price_decimals() );
						$msg = str_replace( '{{' . $variable . '}}', $val, $msg );
						break;
					case 'transaction_id':
						$tid = $order->get_transaction_id();
						$msg = str_replace( '{{' . $variable . '}}', $tid ? $tid : 'N/A', $msg );
						break;
					case 'bacs_account':
						$info = get_option( 'woocommerce_bacs_accounts' );
						$accs = '';
						if ( $info ) {
							foreach ( $info as $acc ) {
								$accs .= '🏦 ' . esc_attr( wp_unslash( $acc['bank_name'] ) ) . "\n";
								$accs .= '👤 ' . esc_attr( wp_unslash( $acc['account_name'] ) ) . "\n";
								$accs .= '🔢 ' . esc_attr( $acc['account_number'] ) . "\n";
							}
						}
						$msg = str_replace( '{{' . $variable . '}}', $accs, $msg );
						break;
					case 'note':
						$msg = str_replace( '{{' . $variable . '}}', 'N/A', $msg );
						break;
					case 'unique_transfer_code':
						$val = $order->get_meta( '_unique_transfer_code', true );
						$msg = str_replace( '{{' . $variable . '}}', $val ? $val : 'N/A', $msg );
						break;
					case 'site_link':
						$msg = str_replace( '{{' . $variable . '}}', site_url(), $msg );
						break;

					// New WP placeholders if there's a user tied to the order.
					case 'wp-first-name':
						$val = $user ? get_user_meta( $user->ID, 'first_name', true ) : '';
						$msg = str_replace( '{{' . $variable . '}}', $val ? $val : 'N/A', $msg );
						break;
					case 'wp-last-name':
						$val = $user ? get_user_meta( $user->ID, 'last_name', true ) : '';
						$msg = str_replace( '{{' . $variable . '}}', $val ? $val : 'N/A', $msg );
						break;
					case 'wp-username':
						$val = $user ? $user->user_login : '';
						$msg = str_replace( '{{' . $variable . '}}', $val ? $val : 'N/A', $msg );
						break;
					case 'wp-nickname':
						$val = $user ? get_user_meta( $user->ID, 'nickname', true ) : '';
						$msg = str_replace( '{{' . $variable . '}}', $val ? $val : 'N/A', $msg );
						break;
					case 'wp-display-name':
						$val = $user ? $user->display_name : '';
						$msg = str_replace( '{{' . $variable . '}}', $val ? $val : 'N/A', $msg );
						break;
					case 'wp-email':
						$val = $user ? $user->user_email : '';
						$msg = str_replace( '{{' . $variable . '}}', $val ? $val : 'N/A', $msg );
						break;
					case 'wp-user-website':
						$val = $user ? $user->user_url : '';
						$msg = str_replace( '{{' . $variable . '}}', $val ? $val : 'N/A', $msg );
						break;
					case 'wp-user-bio':
						$val = $user ? $user->description : '';
						$msg = str_replace( '{{' . $variable . '}}', $val ? $val : 'N/A', $msg );
						break;

					// Additional WooCommerce placeholders.
					case 'wc-order':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_order_number(), $msg );
						break;
					case 'wc-order-id':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_id(), $msg );
						break;
					case 'wc-order-status':
						$status_name = wc_get_order_status_name( $order->get_status() );
						$msg         = str_replace( '{{' . $variable . '}}', $status_name, $msg );
						break;
					case 'wc-order-date':
						$df    = get_option( 'date_format' );
						$tf    = get_option( 'time_format' );
						$od    = $order->get_date_created();
						$d_str = $od ? wp_date( "$df $tf", $od->getTimestamp() ) : '';
						$msg   = str_replace( '{{' . $variable . '}}', $d_str, $msg );
						break;
					case 'wc-product-names':
						$names = array();
						foreach ( $order->get_items() as $item ) {
							$prod = $item->get_product();
							if ( $prod ) {
								$names[] = $prod->get_name();
							}
						}
						$msg = str_replace( '{{' . $variable . '}}', implode( ', ', $names ), $msg );
						break;
					case 'wc-product-names-br':
						$names = array();
						foreach ( $order->get_items() as $item ) {
							$prod = $item->get_product();
							if ( $prod ) {
								$names[] = $prod->get_name();
							}
						}
						$msg = str_replace( '{{' . $variable . '}}', implode( "\n", $names ), $msg );
						break;
					case 'wc-product-names-variable':
						$names = array();
						foreach ( $order->get_items() as $item ) {
							$prod = $item->get_product();
							if ( $prod && $prod->is_type( 'variable' ) ) {
								$names[] = $prod->get_name();
							}
						}
						$msg = str_replace( '{{' . $variable . '}}', implode( ', ', $names ), $msg );
						break;
					case 'wc-product-names-variable-br':
						$names = array();
						foreach ( $order->get_items() as $item ) {
							$prod = $item->get_product();
							if ( $prod && $prod->is_type( 'variable' ) ) {
								$names[] = $prod->get_name();
							}
						}
						$msg = str_replace( '{{' . $variable . '}}', implode( "\n", $names ), $msg );
						break;
					case 'wc-product-name-count':
						$items = $order->get_items();
						$count = count( $items );
						if ( $count > 1 ) {
							$first_item = reset( $items );
							$prod       = $first_item->get_product();
							$first_name = $prod ? $prod->get_name() : '';
							$others     = $count - 1;
							$val        = $first_name . ' and ' . $others . ' more';
						} else {
							// Only 1 item.
							$prod = count( $items ) ? current( $items )->get_product() : null;
							$val  = $prod ? $prod->get_name() : 'N/A';
						}
						$msg = str_replace( '{{' . $variable . '}}', $val, $msg );
						break;
					case 'wc-product-link':
						$links = array();
						foreach ( $order->get_items() as $item ) {
							$prod = $item->get_product();
							if ( $prod ) {
								$links[] = get_permalink( $prod->get_id() );
							}
						}
						$msg = str_replace( '{{' . $variable . '}}', implode( ', ', $links ), $msg );
						break;
					case 'wc-product-link-br':
						$links = array();
						foreach ( $order->get_items() as $item ) {
							$prod = $item->get_product();
							if ( $prod ) {
								$links[] = get_permalink( $prod->get_id() );
							}
						}
						$msg = str_replace( '{{' . $variable . '}}', implode( "\n", $links ), $msg );
						break;
					case 'wc-product-name-link':
						$pairs = array();
						foreach ( $order->get_items() as $item ) {
							$prod = $item->get_product();
							if ( $prod ) {
								$url     = get_permalink( $prod->get_id() );
								$pairs[] = $prod->get_name() . ' (' . $url . ')';
							}
						}
						$msg = str_replace( '{{' . $variable . '}}', implode( ', ', $pairs ), $msg );
						break;
					case 'wc-product-name-link-br':
						$pairs = array();
						foreach ( $order->get_items() as $item ) {
							$prod = $item->get_product();
							if ( $prod ) {
								$url     = get_permalink( $prod->get_id() );
								$pairs[] = $prod->get_name() . ' (' . $url . ')';
							}
						}
						$msg = str_replace( '{{' . $variable . '}}', implode( "\n", $pairs ), $msg );
						break;
					case 'wc-total-products':
						$count = count( $order->get_items() );
						$msg   = str_replace( '{{' . $variable . '}}', $count, $msg );
						break;
					case 'wc-total-items':
						$qty = 0;
						foreach ( $order->get_items() as $item ) {
							$qty += $item->get_quantity();
						}
						$msg = str_replace( '{{' . $variable . '}}', $qty, $msg );
						break;
					case 'wc-order-items':
						$lines = array();
						foreach ( $order->get_items() as $item ) {
							$prod = $item->get_product();
							if ( $prod ) {
								$lines[] = $prod->get_name() . ' x ' . $item->get_quantity();
							}
						}
						$msg = str_replace( '{{' . $variable . '}}', implode( ', ', $lines ), $msg );
						break;
					case 'wc-order-items-br':
						$lines = array();
						foreach ( $order->get_items() as $item ) {
							$prod = $item->get_product();
							if ( $prod ) {
								$lines[] = $prod->get_name() . ' x ' . $item->get_quantity();
							}
						}
						$msg = str_replace( '{{' . $variable . '}}', implode( "\n", $lines ), $msg );
						break;
					case 'wc-order-items-variable':
						$lines = array();
						foreach ( $order->get_items() as $item ) {
							$prod = $item->get_product();
							if ( $prod && $prod->is_type( 'variable' ) ) {
								$lines[] = $prod->get_name() . ' x ' . $item->get_quantity();
							}
						}
						$msg = str_replace( '{{' . $variable . '}}', implode( ', ', $lines ), $msg );
						break;
					case 'wc-order-items-variable-br':
						$lines = array();
						foreach ( $order->get_items() as $item ) {
							$prod = $item->get_product();
							if ( $prod && $prod->is_type( 'variable' ) ) {
								$lines[] = $prod->get_name() . ' x ' . $item->get_quantity();
							}
						}
						$msg = str_replace( '{{' . $variable . '}}', implode( "\n", $lines ), $msg );
						break;
					case 'wc-order-items-price':
						$lines = array();
						foreach ( $order->get_items() as $item ) {
							$prod = $item->get_product();
							if ( $prod ) {
								$lines[] = $prod->get_name() . ' x ' . $item->get_quantity() . ' - ' .
										$currency_symb . number_format( $item->get_total(), wc_get_price_decimals() );
							}
						}
						$msg = str_replace( '{{' . $variable . '}}', implode( ', ', $lines ), $msg );
						break;
					case 'wc-order-items-price-br':
						$lines = array();
						foreach ( $order->get_items() as $item ) {
							$prod = $item->get_product();
							if ( $prod ) {
								$lines[] = $prod->get_name() . ' x ' . $item->get_quantity() . ' - ' .
										$currency_symb . number_format( $item->get_total(), wc_get_price_decimals() );
							}
						}
						$msg = str_replace( '{{' . $variable . '}}', implode( "\n", $lines ), $msg );
						break;
					case 'wc-all-order-items-br':
						$detail_lines = array();
						foreach ( $order->get_items() as $item ) {
							$prod = $item->get_product();
							if ( $prod ) {
								$detail_lines[] = sprintf(
									'%s x %d = %s%s',
									$prod->get_name(),
									$item->get_quantity(),
									$currency_symb,
									number_format( $item->get_total(), wc_get_price_decimals() )
								);
							}
						}
						$msg = str_replace( '{{' . $variable . '}}', implode( "\n", $detail_lines ), $msg );
						break;
					case 'wc-sku':
						$skus = array();
						foreach ( $order->get_items() as $item ) {
							$prod = $item->get_product();
							if ( $prod ) {
								$sku = $prod->get_sku();
								if ( $sku ) {
									$skus[] = $sku;
								}
							}
						}
						$msg = str_replace( '{{' . $variable . '}}', implode( ', ', $skus ), $msg );
						break;
					case 'wc-sku-br':
						$skus = array();
						foreach ( $order->get_items() as $item ) {
							$prod = $item->get_product();
							if ( $prod ) {
								$sku = $prod->get_sku();
								if ( $sku ) {
									$skus[] = $sku;
								}
							}
						}
						$msg = str_replace( '{{' . $variable . '}}', implode( "\n", $skus ), $msg );
						break;
					case 'wc-order-amount':
						$val = number_format( $order->get_total(), wc_get_price_decimals() );
						$msg = str_replace( '{{' . $variable . '}}', $val, $msg );
						break;
					case 'wc-discount':
						$val = number_format( $order->get_total_discount(), wc_get_price_decimals() );
						$msg = str_replace( '{{' . $variable . '}}', $val, $msg );
						break;
					case 'wc-tax':
						$val = number_format( $order->get_total_tax(), wc_get_price_decimals() );
						$msg = str_replace( '{{' . $variable . '}}', $val, $msg );
						break;
					case 'wc-order-amount-ex-tax':
						$total_ex_tax = $order->get_total() - $order->get_total_tax();
						$val          = number_format( $total_ex_tax, wc_get_price_decimals() );
						$msg          = str_replace( '{{' . $variable . '}}', $val, $msg );
						break;
					case 'wc-payment-method':
						$val = $order->get_payment_method();
						$msg = str_replace( '{{' . $variable . '}}', $val ? $val : 'N/A', $msg );
						break;
					case 'wc-transaction-id':
						$tid = $order->get_transaction_id();
						$msg = str_replace( '{{' . $variable . '}}', $tid ? $tid : 'N/A', $msg );
						break;
					case 'wc-shipping-method':
						$val = $order->get_shipping_method();
						$msg = str_replace( '{{' . $variable . '}}', $val ? $val : 'N/A', $msg );
						break;
					case 'wc-shipping-cost':
						$val = number_format( $order->get_shipping_total(), wc_get_price_decimals() );
						$msg = str_replace( '{{' . $variable . '}}', $val, $msg );
						break;
					case 'wc-refund-amount':
						$val = number_format( $order->get_total_refunded(), wc_get_price_decimals() );
						$msg = str_replace( '{{' . $variable . '}}', $val, $msg );
						break;
					case 'wc-refund-reason':
						$refunds = $order->get_refunds();
						$reasons = array();
						foreach ( $refunds as $refund ) {
							$reason = $refund->get_reason();
							if ( $reason ) {
								$reasons[] = $reason;
							}
						}
						$msg = str_replace( '{{' . $variable . '}}', implode( ', ', $reasons ), $msg );
						break;
					case 'wc-order-notes':
						$val = $order->get_customer_note();
						$msg = str_replace( '{{' . $variable . '}}', $val ? $val : 'N/A', $msg );
						break;

					// WooCommerce Billing/Shipping with hyphens.
					case 'wc_billing_first_name':
					case 'wc-billing-first-name':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_billing_first_name(), $msg );
						break;
					case 'wc_billing_last_name':
					case 'wc-billing-last-name':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_billing_last_name(), $msg );
						break;
					case 'wc_billing_company':
					case 'wc-billing-company':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_billing_company(), $msg );
						break;
					case 'wc_billing_address_line_1':
					case 'wc_billing_address_1':
					case 'wc-billing-address-line-1':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_billing_address_1(), $msg );
						break;
					case 'wc_billing_address_line_2':
					case 'wc_billing_address_2':
					case 'wc-billing-address-line-2':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_billing_address_2(), $msg );
						break;
					case 'wc_billing_city':
					case 'wc-billing-city':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_billing_city(), $msg );
						break;
					case 'wc_billing_postcode':
					case 'wc-billing-postcode':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_billing_postcode(), $msg );
						break;
					case 'wc_billing_state':
					case 'wc-billing-state':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_billing_state(), $msg );
						break;
					case 'wc_billing_country':
					case 'wc-billing-country':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_billing_country(), $msg );
						break;
					case 'wc_billing_email':
					case 'wc-billing-email':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_billing_email(), $msg );
						break;
					case 'wc_billing_phone':
					case 'wc-billing-phone':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_billing_phone(), $msg );
						break;
					case 'wc_shipping_first_name':
					case 'wc-shipping-first-name':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_shipping_first_name(), $msg );
						break;
					case 'wc_shipping_last_name':
					case 'wc-shipping-last-name':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_shipping_last_name(), $msg );
						break;
					case 'wc_shipping_company':
					case 'wc-shipping-company':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_shipping_company(), $msg );
						break;
					case 'wc_shipping_address_line_1':
					case 'wc_shipping_address_1':
					case 'wc-shipping-address-line-1':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_shipping_address_1(), $msg );
						break;
					case 'wc_shipping_address_line_2':
					case 'wc_shipping_address_2':
					case 'wc-shipping-address-line-2':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_shipping_address_2(), $msg );
						break;
					case 'wc_shipping_city':
					case 'wc-shipping-city':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_shipping_city(), $msg );
						break;
					case 'wc_shipping_postcode':
					case 'wc-shipping-postcode':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_shipping_postcode(), $msg );
						break;
					case 'wc_shipping_state':
					case 'wc-shipping-state':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_shipping_state(), $msg );
						break;
					case 'wc_shipping_country':
					case 'wc-shipping-country':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_shipping_country(), $msg );
						break;

					// Legacy Billing/Shipping explicit cases.
					case 'billing_first_name':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_billing_first_name() ? $order->get_billing_first_name() : 'N/A', $msg );
						break;
					case 'billing_last_name':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_billing_last_name() ? $order->get_billing_last_name() : 'N/A', $msg );
						break;
					case 'billing_email':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_billing_email() ? $order->get_billing_email() : 'N/A', $msg );
						break;
					case 'billing_phone':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_billing_phone() ? $order->get_billing_phone() : 'N/A', $msg );
						break;
					case 'billing_address_1':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_billing_address_1() ? $order->get_billing_address_1() : 'N/A', $msg );
						break;
					case 'billing_address_2':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_billing_address_2() ? $order->get_billing_address_2() : 'N/A', $msg );
						break;
					case 'billing_city':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_billing_city() ? $order->get_billing_city() : 'N/A', $msg );
						break;
					case 'billing_postcode':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_billing_postcode() ? $order->get_billing_postcode() : 'N/A', $msg );
						break;
					case 'billing_state':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_billing_state() ? $order->get_billing_state() : 'N/A', $msg );
						break;
					case 'billing_country':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_billing_country() ? $order->get_billing_country() : 'N/A', $msg );
						break;
					case 'shipping_first_name':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_shipping_first_name() ? $order->get_shipping_first_name() : 'N/A', $msg );
						break;
					case 'shipping_last_name':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_shipping_last_name() ? $order->get_shipping_last_name() : 'N/A', $msg );
						break;
					case 'shipping_address_1':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_shipping_address_1() ? $order->get_shipping_address_1() : 'N/A', $msg );
						break;
					case 'shipping_city':
						$msg = str_replace( '{{' . $variable . '}}', $order->get_shipping_city() ? $order->get_shipping_city() : 'N/A', $msg );
						break;

					default:
						// If it's a known placeholder in $wawp_wa not handled above, or custom meta.
						$meta_val = $order->get_meta( $var_lower );
						if ( ! $meta_val ) {
							// Try '_field' or 'field' in post meta.
							$meta_val = get_post_meta( $order->get_id(), '_' . $var_lower, true );
							if ( ! $meta_val ) {
								$meta_val = get_post_meta( $order->get_id(), $var_lower, true );
							}
						}
						// Fallback to user meta if order meta is empty.
						if ( ! $meta_val && $user ) {
							$meta_val = get_user_meta( $user->ID, $var_lower, true );
						}
						if ( ! $meta_val ) {
							$meta_val = 'N/A';
						}
						$msg = str_replace( '{{' . $variable . '}}', $meta_val, $msg );
						break;
				}
			} else {
				// --------------------------------------------------------------
				// 4) If no order AND no user, just set placeholder to "N/A".
				// --------------------------------------------------------------
				$msg = str_replace( '{{' . $variable . '}}', 'N/A', $msg );
			}
		}

		// Parse spintax formats like {السلام عليكم|مرحباً|أهلاً بك} at the very end.
		$msg = self::parse_spintax( $msg );

		return $msg;
	}

	/**
	 * Parse recursive Spintax blocks in a message string.
	 * Format: {option1|option2|option3}
	 *
	 * @param string $msg Message text.
	 * @return string Message with parsed spintax.
	 */
	public static function parse_spintax( $msg ) {
		if ( empty( $msg ) ) {
			return '';
		}

		// Find the innermost spintax matches e.g. {option1|option2|option3}.
		while ( preg_match( '/\{([^{}|]*\|[^{}]+)\}/', $msg, $matches ) ) {
			$parts    = explode( '|', $matches[1] );
			$selected = $parts[ array_rand( $parts ) ];
			$msg      = str_replace( $matches[0], $selected, $msg );
		}

		return $msg;
	}
}
