<?php
/**
 * WooCommerce Triggers Trait.
 *
 * @package automation-web-platform
 */

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

trait WAWP_Woocommerce_Triggers {
	/**
	 * Pending order status notifications due to missing billing phone during early hooks.
	 *
	 * @var array
	 */
	private static $pending_notifications = array();

	/**
	 * Already processed order status notifications in the current request.
	 *
	 * @var array
	 */
	private static $processed_notifications = array();
	/**
	 * Handle manual WC status notification.
	 *
	 * @param WC_Order|int $order Order object or ID.
	 */
	public function handle_wc_manual_status_notify( $order ) {
		if ( ! function_exists( 'wc_get_order' ) ) {
			return;
		}
		if ( ! ( class_exists( 'WC_Order' ) && $order instanceof WC_Order ) ) {
			$order = wc_get_order( $order );
			if ( ! $order ) {
				return;
			}
		}

		$status = $order->get_status();
		$this->handle_order_status_change( $order->get_id(), $status, $status, $order, esc_html__( 'Manual Notification Request', 'automation-web-platform' ) );
	}

	/**
	 * Handle WC order status change.
	 *
	 * @param int          $order_id       Order ID.
	 * @param string       $old_status     Old status.
	 * @param string       $new_status     New status.
	 * @param WC_Order|int $order          Order object or ID.
	 * @param string|null  $force_log_label Optional log label override.
	 */
	public function handle_order_status_change( $order_id, $old_status, $new_status, $order, $force_log_label = null ) {
		// Check if already processed in this request to avoid duplicate notifications.
		$cache_key = $order_id . '_' . $new_status;
		if ( isset( self::$processed_notifications[ $cache_key ] ) ) {
			return;
		}

		if ( empty( $this->wawp_db_manager ) ) {
			return;
		}

		if ( ! function_exists( 'wc_get_order' ) ) {
			return;
		}

		if ( ! ( class_exists( 'WC_Order' ) && $order instanceof WC_Order ) ) {
			$order = wc_get_order( $order_id );
			if ( ! $order ) {
				return;
			}
		}

		// Avoid duplicate notifications on multi-vendor sites by skipping child orders/sub-orders.
		if ( method_exists( $order, 'get_parent_id' ) && $order->get_parent_id() > 0 ) {
			return;
		}

		$settings    = $this->get_settings();
		$user_id     = $order->get_customer_id();
		$locale      = $user_id ? get_user_locale( $user_id ) : ( $settings['main_language_code'] ? $settings['main_language_code'] : ( WAWP::instance()->get_wawp_setting( 'WPLANG' ) ? WAWP::instance()->get_wawp_setting( 'WPLANG' ) : 'en_US' ) );
		$trigger_key = 'wc_status_' . $new_status;
		$rules       = $this->get_matching_rules( $settings, $locale, $trigger_key );
		if ( empty( $rules ) ) {
			return;
		}

		$billing_email = $order->get_billing_email();
		$billing_phone = $order->get_billing_phone();
		if ( empty( $billing_phone ) && $user_id ) {
			$billing_phone = WAWP()->user_manager->get_user_phone( $user_id );
		}

		// If billing phone is empty, queue it for processing later in the request when checkout finishes.
		if ( empty( $billing_phone ) ) {
			if ( ! isset( self::$pending_notifications[ $order_id ] ) ) {
				self::$pending_notifications[ $order_id ] = array();
			}
			self::$pending_notifications[ $order_id ][ $new_status ] = array(
				'old_status'      => $old_status,
				'new_status'      => $new_status,
				'force_log_label' => $force_log_label,
			);
			return;
		}

		// Mark as processed to prevent duplicates during the same request.
		self::$processed_notifications[ $cache_key ] = true;

		$all_statuses  = function_exists( 'wc_get_order_statuses' ) ? wc_get_order_statuses() : array();
		$new_label     = isset( $all_statuses[ 'wc-' . $new_status ] ) ? $all_statuses[ 'wc-' . $new_status ] : $new_status;
		$old_label     = isset( $all_statuses[ 'wc-' . $old_status ] ) ? $all_statuses[ 'wc-' . $old_status ] : $old_status;
		$customer_name = $order->get_formatted_billing_full_name() ? $order->get_formatted_billing_full_name() : ( $user_id ? get_userdata( $user_id )->display_name : esc_html__( 'Customer', 'automation-web-platform' ) );

		$order_date           = $order->get_date_created() ? $order->get_date_created()->date_i18n( wc_date_format() ) : '';
		$order_link           = $order->get_checkout_order_received_url();
		$admin_order_link     = admin_url( 'post.php?post=' . $order->get_id() . '&action=edit' );
		$billing_country_name = '';
		if ( function_exists( 'WC' ) && $order->get_billing_country() ) {
			$countries            = WC()->countries->get_countries();
			$billing_country_name = $countries[ $order->get_billing_country() ] ?? $order->get_billing_country();
		}

		// Shipping tracking — read common meta keys used by WooCommerce Shipment Tracking and similar plugins.
		$tracking_number   = $order->get_meta( '_tracking_number', true );
		$tracking_provider = $order->get_meta( '_tracking_provider', true );
		$tracking_link     = $order->get_meta( '_tracking_link', true );
		$date_shipped      = $order->get_meta( '_date_shipped', true );
		// Also try WC Shipment Tracking plugin format (array of items).
		if ( empty( $tracking_number ) ) {
			$tracking_items = $order->get_meta( '_wc_shipment_tracking_items', true );
			if ( is_array( $tracking_items ) && ! empty( $tracking_items ) ) {
				$first_item        = reset( $tracking_items );
				$tracking_number   = $first_item['tracking_number'] ?? '';
				$tracking_provider = $first_item['tracking_provider'] ?? $first_item['custom_tracking_provider'] ?? '';
				$tracking_link     = $first_item['custom_tracking_link'] ?? '';
				$date_shipped      = ! empty( $first_item['date_shipped'] ) ? gmdate( 'Y-m-d', (int) $first_item['date_shipped'] ) : '';
			}
		}

		$replacements_user = array(
			'{{order_id}}'               => $order_id,
			'{{wc-order}}'               => $order->get_order_number(),
			'{{order_date}}'             => $order_date,
			'{{customer_name}}'          => $customer_name,
			'{{billing_first_name}}'     => $order->get_billing_first_name(),
			'{{billing_last_name}}'      => $order->get_billing_last_name(),
			'{{billing_email}}'          => $billing_email,
			'{{billing_phone}}'          => $billing_phone,
			'{{billing_address_1}}'      => $order->get_billing_address_1(),
			'{{billing_address_2}}'      => $order->get_billing_address_2(),
			'{{billing_city}}'           => $order->get_billing_city(),
			'{{billing_postcode}}'       => $order->get_billing_postcode(),
			'{{billing_state}}'          => $order->get_billing_state(),
			'{{billing_country}}'        => $billing_country_name,
			'{{shipping_first_name}}'    => $order->get_shipping_first_name(),
			'{{shipping_last_name}}'     => $order->get_shipping_last_name(),
			'{{shipping_address_1}}'     => $order->get_shipping_address_1(),
			'{{shipping_address_2}}'     => $order->get_shipping_address_2(),
			'{{shipping_city}}'          => $order->get_shipping_city(),
			'{{shipping_postcode}}'      => $order->get_shipping_postcode(),
			'{{shipping_state}}'         => $order->get_shipping_state(),
			'{{shipping_country}}'       => $order->get_shipping_country(),
			'{{order_total}}'            => html_entity_decode( wp_strip_all_tags( $order->get_formatted_order_total() ), ENT_QUOTES, 'UTF-8' ),
			'{{order_subtotal}}'         => html_entity_decode( wp_strip_all_tags( wc_price( $order->get_subtotal() ) ), ENT_QUOTES, 'UTF-8' ),
			'{{order_discount}}'         => html_entity_decode( wp_strip_all_tags( wc_price( $order->get_total_discount() ) ), ENT_QUOTES, 'UTF-8' ),
			'{{order_tax}}'              => html_entity_decode( wp_strip_all_tags( wc_price( $order->get_total_tax() ) ), ENT_QUOTES, 'UTF-8' ),
			'{{order_shipping}}'         => html_entity_decode( wp_strip_all_tags( wc_price( $order->get_shipping_total() ) ), ENT_QUOTES, 'UTF-8' ),
			'{{order_link}}'             => $order_link,
			'{{admin_order_link}}'       => $admin_order_link,
			'{{payment_method_title}}'   => $order->get_payment_method_title(),
			'{{transaction_id}}'         => $order->get_transaction_id(),
			'{{shipping_method_title}}'  => $order->get_shipping_method(),
			'{{cust_note}}'              => $order->get_customer_note(),
			'{{status}}'                 => $new_label,
			'{{order_status_label}}'     => $new_label,
			'{{old_order_status_label}}' => $old_label,
			'{{sitename}}'               => get_bloginfo( 'name' ),
			'{{siteurl}}'                => home_url(),
			'{{tagline}}'                => get_bloginfo( 'description' ),
			'{{privacy-policy}}'         => function_exists( 'get_privacy_policy_url' ) ? get_privacy_policy_url() : '',
			'{{current_date_time}}'      => wp_date( 'Y-m-d H:i:s' ),
			'{{user_email}}'             => $billing_email,
			'{{_tracking_number}}'       => $tracking_number,
			'{{_tracking_provider}}'     => $tracking_provider,
			'{{_tracking_link}}'         => $tracking_link,
			'{{_date_shipped}}'          => $date_shipped,
		);

		$recipient_user = array(
			'user_id'      => $user_id,
			'email'        => $billing_email,
			'phone'        => $billing_phone,
			'display_name' => $customer_name,
		);

		$log_base = $force_log_label ? $force_log_label : sprintf( 'Order Status %s - ', $new_label );
		$context  = $this->prepare_object_context( $order );

		foreach ( $rules as $rule ) {
			$this->apply_image_overrides( $rule, $context );
			if ( ! $this->evaluate_rule_filters( $rule, $context ) ) {
				if ( str_contains( $rule['sender_type'] ?? '', 'admin' ) ) {
					$rule['sender_type'] = str_replace( 'user_', '', $rule['sender_type'] );
				} else {
					continue;
				}
			}

			$this->schedule_or_send( $rule, $replacements_user, $recipient_user, $log_base, $order_id, $trigger_key );
		}
	}

	/**
	 * Handle new WC customer note trigger.
	 *
	 * @param array $note_data Note data.
	 */
	public function handle_new_customer_note_trigger( $note_data ) {
		if ( empty( $note_data['order_id'] ) || empty( $note_data['customer_note'] ) ) {
			return;
		}

		$object_id       = $note_data['order_id'];
		$is_subscription = function_exists( 'wcs_is_subscription' ) && wcs_is_subscription( $object_id );
		$trigger_key     = $is_subscription ? 'wc_sub_note_added' : 'wc_order_note_added';
		$object          = null;
		if ( $is_subscription && function_exists( 'wcs_get_subscription' ) ) {
			$object = wcs_get_subscription( $object_id );
		} elseif ( function_exists( 'wc_get_order' ) ) {
			$object = wc_get_order( $object_id );
		}

		if ( ! $object ) {
			return;
		}

		// Avoid duplicate note notifications on child orders.
		if ( is_a( $object, 'WC_Order' ) && method_exists( $object, 'get_parent_id' ) && $object->get_parent_id() > 0 ) {
			return;
		}

		$settings = $this->get_settings();
		$user_id  = $object->get_customer_id();
		$locale   = $user_id ? get_user_locale( $user_id ) : ( $settings['main_language_code'] ? $settings['main_language_code'] : 'en_US' );
		$rules    = $this->get_matching_rules( $settings, $locale, $trigger_key );

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

		$customer_name = $object->get_formatted_billing_full_name() ? $object->get_formatted_billing_full_name() : ( $user_id ? get_userdata( $user_id )->display_name : esc_html__( 'Customer', 'automation-web-platform' ) );

		$replacements = array(
			'{{customer_name}}' => $customer_name,
			'{{user_email}}'    => $object->get_billing_email(),
			'{{sitename}}'      => get_bloginfo( 'name' ),
			'{{cust_note}}'     => wp_strip_all_tags( $note_data['customer_note'] ),
		);

		if ( $is_subscription ) {
			$replacements['{{subscription_id}}']    = $object_id;
			$replacements['{{subscription_total}}'] = html_entity_decode( wp_strip_all_tags( $object->get_formatted_order_total() ), ENT_QUOTES, 'UTF-8' );
			/* translators: %s: subscription id */
			$log_base = sprintf( __( 'Subscription Note Added (#%s)', 'automation-web-platform' ), $object_id );
		} else {
			$replacements['{{order_id}}']    = $object_id;
			$replacements['{{order_total}}'] = html_entity_decode( wp_strip_all_tags( $object->get_formatted_order_total() ), ENT_QUOTES, 'UTF-8' );
			/* translators: %s: order id */
			$log_base = sprintf( __( 'Order Note Added (#%s)', 'automation-web-platform' ), $object_id );
		}

		$recipient_user = array(
			'user_id'      => $user_id,
			'email'        => $object->get_billing_email(),
			'phone'        => $object->get_billing_phone(),
			'display_name' => $customer_name,
		);

		foreach ( $rules as $rule ) {
			$this->schedule_or_send( $rule, $replacements, $recipient_user, $log_base, $object_id, $trigger_key );
		}
	}

	/**
	 * Process pending order status notifications once order metadata (billing phone) is saved.
	 *
	 * @param int $order_id Order ID.
	 */
	public function process_pending_order_notifications( $order_id ) {
		if ( empty( self::$pending_notifications[ $order_id ] ) ) {
			return;
		}

		if ( ! function_exists( 'wc_get_order' ) ) {
			return;
		}

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

		$billing_phone = $order->get_billing_phone();
		$user_id       = $order->get_customer_id();
		if ( empty( $billing_phone ) && $user_id ) {
			$billing_phone = WAWP()->user_manager->get_user_phone( $user_id );
		}

		if ( empty( $billing_phone ) ) {
			return; // Phone is still not populated.
		}

		$pending = self::$pending_notifications[ $order_id ];
		unset( self::$pending_notifications[ $order_id ] );

		foreach ( $pending as $status => $args ) {
			$this->handle_order_status_change(
				$order_id,
				$args['old_status'],
				$args['new_status'],
				$order,
				$args['force_log_label']
			);
		}
	}
}
