<?php

namespace orderflow\Facebook;

use orderflow\Facebook\EventTypes;
use orderflow\Facebook\SingleEvent;
use orderflow\Facebook\EventIdGenerator;
use PYS_PRO_GLOBAL\FacebookAds\Object\ServerSide\EventRequest;
use PYS_PRO_GLOBAL\FacebookAds\Api;
use PYS_PRO_GLOBAL\FacebookAds\Http\Exception\RequestException;

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

/**
 * Custom Order Status Event Manager
 * Handles sending custom Facebook server-side events when order status changes
 */
class Custom_Order_Status_Event_Manager {

	private static $_instance;

	/**
	 * Map custom order statuses to Facebook event names
	 */
	private $status_event_map = [
		'ads-recovered'  => 'Recovered',
		'ads-confirmed'  => 'Confirmed',
		'ads-shipping'   => 'Shipping',
		'ads-returned'   => 'Returned',
		'ads-delivered'  => 'Delivered',
		//'ads-incomplete' => 'Incomplete',
	];

	public static function instance() {
		if ( is_null( self::$_instance ) ) {
			self::$_instance = new self();
		}
		return self::$_instance;
	}

	public function __construct() {
		// Hook to send custom events when order status changes
		add_action( 'woocommerce_order_status_changed', array( $this, 'send_custom_status_event' ), 20, 3 );
	}

	/**
	 * Send custom event when order status changes to one of the custom statuses
	 *
	 * @param int $order_id
	 * @param string $old_status
	 * @param string $new_status
	 */
	public function send_custom_status_event( $order_id, $old_status, $new_status ) {
		error_log( '[CustomOrderStatusEventManager] send_custom_status_event called - Order ID: ' . $order_id . ', Old Status: ' . $old_status . ', New Status: ' . $new_status );

		// Remove 'wc-' prefix if present
		$new_status = str_replace( 'wc-', '', $new_status );
		error_log( '[CustomOrderStatusEventManager] Normalized new status: ' . $new_status );

		// Check if this is one of our custom statuses (excluding ads-purchase which is handled separately)
		if ( ! isset( $this->status_event_map[ $new_status ] ) ) {
			error_log( '[CustomOrderStatusEventManager] Status ' . $new_status . ' is not a custom status, skipping' );
			return;
		}

		$order = wc_get_order( $order_id );
		if ( ! $order ) {
			error_log( '[CustomOrderStatusEventManager] Order not found for order_id: ' . $order_id );
			return;
		}

		// Check if Facebook is configured
		if ( ! Facebook()->configured() ) {
			error_log( '[CustomOrderStatusEventManager] Facebook pixel is not configured, skipping' );
			return;
		}

		// Check if server API is enabled
		if ( ! Facebook()->isServerApiEnabled() ) {
			error_log( '[CustomOrderStatusEventManager] Facebook Server API is not enabled, skipping' );
			return;
		}

		// Get event name from status map
		$event_name = $this->status_event_map[ $new_status ];
		error_log( '[CustomOrderStatusEventManager] Sending custom event: ' . $event_name . ' for order_id: ' . $order_id );

		// Generate and send the custom event
		$this->generate_and_send_custom_event( $order, $event_name );
	}

	/**
	 * Generate custom event data and send to Facebook using saved customer data
	 *
	 * @param \WC_Order $order
	 * @param string $event_name Custom event name (e.g., 'Recovered', 'Confirmed', etc.)
	 */
	private function generate_and_send_custom_event( $order, $event_name ) {
		error_log( '[CustomOrderStatusEventManager] Generating custom event: ' . $event_name . ' for order_id: ' . $order->get_id() );

		// Get saved purchase event data (always saved by PurchaseEventManager now)
		$purchase_event_data = null;
		if ( isWooCommerceVersionGte( '3.0.0' ) ) {
			$purchase_event_data = $order->get_meta( '_ads_purchase_event_data', true );
		} else {
			$purchase_event_data = get_post_meta( $order->get_id(), '_ads_purchase_event_data', true );
		}

		// If no saved data, cannot generate now because it will use admin's fbp/fbc instead of customer's
		if ( ! $purchase_event_data || empty( $purchase_event_data ) ) {
			error_log( '[CustomOrderStatusEventManager] No saved purchase event data found for order_id: ' . $order->get_id() . '. Cannot generate now as it would use admin fbp/fbc instead of customer data. Event will not be sent.' );
			return;
		}

		error_log( '[CustomOrderStatusEventManager] Using saved purchase event data for order_id: ' . $order->get_id() );

		// Check if server event data exists
		if ( ! isset( $purchase_event_data['server_event_data'] ) || empty( $purchase_event_data['server_event_data'] ) ) {
			error_log( '[CustomOrderStatusEventManager] No server event data found in saved data for order_id: ' . $order->get_id() );
			return;
		}

		// Get pixel IDs from saved data
		$pixel_ids = isset( $purchase_event_data['pixel_ids'] ) ? $purchase_event_data['pixel_ids'] : array();

		if ( empty( $pixel_ids ) ) {
			error_log( '[CustomOrderStatusEventManager] No pixel IDs found in saved data' );
			return;
		}

		// Recreate server event from saved data but change event name to custom event name
		$server_event = $this->recreate_server_event_for_custom_event( $purchase_event_data['server_event_data'], $event_name, $order->get_id() );

		if ( ! $server_event ) {
			error_log( '[CustomOrderStatusEventManager] Failed to recreate server event from saved data' );
			return;
		}

		// Store saved customer data to prevent admin data from overwriting it
		$saved_user_data = isset( $purchase_event_data['server_event_data']['user_data'] ) ? $purchase_event_data['server_event_data']['user_data'] : null;

		// Send event directly to Facebook API using saved customer data
		if ( Facebook()->isServerApiEnabled() ) {
			$this->send_event_directly_to_api( $pixel_ids, $server_event, $saved_user_data, $order->get_id() );
			error_log( '[CustomOrderStatusEventManager] Custom event sent directly to Facebook API using saved customer data: ' . $event_name . ' for order_id: ' . $order->get_id() );
		} else {
			error_log( '[CustomOrderStatusEventManager] Facebook Server API is not enabled' );
		}
	}

	/**
	 * Recreate server event object from saved data but with custom event name
	 * Uses the same saved customer data from purchase event
	 *
	 * @param array $server_event_data Saved server event data from purchase event
	 * @param string $custom_event_name Custom event name (e.g., 'Recovered', 'Confirmed', etc.)
	 * @param int $order_id Order ID for generating new event ID
	 * @return \PYS_PRO_GLOBAL\FacebookAds\Object\ServerSide\Event|null
	 */
	private function recreate_server_event_for_custom_event( $server_event_data, $custom_event_name, $order_id ) {
		if ( empty( $server_event_data ) ) {
			return null;
		}

		// Create new Event object
		$event = new \PYS_PRO_GLOBAL\FacebookAds\Object\ServerSide\Event();

		// Set basic properties - use custom event name and current time
		$event->setEventName( $custom_event_name );
		$event->setEventTime( time() );
		$event->setEventId( EventIdGenerator::guidv4() ); // Generate new event ID for custom event
		
		if ( isset( $server_event_data['event_source_url'] ) ) {
			$event->setEventSourceUrl( $server_event_data['event_source_url'] );
		}
		if ( isset( $server_event_data['action_source'] ) ) {
			$event->setActionSource( $server_event_data['action_source'] );
		}

		// Recreate user data from saved customer data (fbp, fbc, IP, User Agent, etc.)
		if ( isset( $server_event_data['user_data'] ) && is_array( $server_event_data['user_data'] ) ) {
			$user_data = new \PYS_PRO_GLOBAL\FacebookAds\Object\ServerSide\UserData();

			$ud = $server_event_data['user_data'];
			if ( isset( $ud['fbp'] ) && ! empty( $ud['fbp'] ) ) {
				$user_data->setFbp( $ud['fbp'] );
			}
			if ( isset( $ud['fbc'] ) && ! empty( $ud['fbc'] ) ) {
				$user_data->setFbc( $ud['fbc'] );
			}
			if ( isset( $ud['client_ip_address'] ) && ! empty( $ud['client_ip_address'] ) ) {
				$user_data->setClientIpAddress( $ud['client_ip_address'] );
			}
			if ( isset( $ud['client_user_agent'] ) && ! empty( $ud['client_user_agent'] ) ) {
				$user_data->setClientUserAgent( $ud['client_user_agent'] );
			}
			if ( isset( $ud['email'] ) && ! empty( $ud['email'] ) ) {
				$user_data->setEmail( $ud['email'] );
			}
			if ( isset( $ud['phone'] ) && ! empty( $ud['phone'] ) ) {
				$user_data->setPhone( $ud['phone'] );
			}
			if ( isset( $ud['first_name'] ) && ! empty( $ud['first_name'] ) ) {
				$user_data->setFirstName( $ud['first_name'] );
			}
			if ( isset( $ud['last_name'] ) && ! empty( $ud['last_name'] ) ) {
				$user_data->setLastName( $ud['last_name'] );
			}
			if ( isset( $ud['city'] ) && ! empty( $ud['city'] ) ) {
				$user_data->setCity( $ud['city'] );
			}
			if ( isset( $ud['state'] ) && ! empty( $ud['state'] ) ) {
				$user_data->setState( $ud['state'] );
			}
			if ( isset( $ud['zip_code'] ) && ! empty( $ud['zip_code'] ) ) {
				$user_data->setZipCode( $ud['zip_code'] );
			}
			if ( isset( $ud['country_code'] ) && ! empty( $ud['country_code'] ) ) {
				$user_data->setCountryCode( $ud['country_code'] );
			}
			if ( isset( $ud['external_id'] ) && ! empty( $ud['external_id'] ) ) {
				$user_data->setExternalId( $ud['external_id'] );
			}
			if ( isset( $ud['fb_login_id'] ) && ! empty( $ud['fb_login_id'] ) ) {
				$user_data->setFbLoginId( $ud['fb_login_id'] );
			}

			$event->setUserData( $user_data );
		}

		// Recreate custom data (order value, currency, products, etc.) - same as purchase event
		if ( isset( $server_event_data['custom_data'] ) && is_array( $server_event_data['custom_data'] ) ) {
			$custom_data = new \PYS_PRO_GLOBAL\FacebookAds\Object\ServerSide\CustomData();

			$cd = $server_event_data['custom_data'];
			if ( isset( $cd['value'] ) ) {
				$custom_data->setValue( $cd['value'] );
			}
			if ( isset( $cd['currency'] ) ) {
				$custom_data->setCurrency( strtoupper($cd['currency']) );
			}
			if ( isset( $cd['content_type'] ) ) {
				$custom_data->setContentType( $cd['content_type'] );
			}
			if ( isset( $cd['content_ids'] ) && is_array( $cd['content_ids'] ) ) {
				$custom_data->setContentIds( $cd['content_ids'] );
			}
			if ( isset( $cd['content_name'] ) ) {
				$custom_data->setContentName( $cd['content_name'] );
			}
			if ( isset( $cd['content_category'] ) ) {
				$custom_data->setContentCategory( $cd['content_category'] );
			}
			if ( isset( $cd['num_items'] ) ) {
				$custom_data->setNumItems( $cd['num_items'] );
			}

			// Recreate contents array
			if ( isset( $cd['contents'] ) && is_array( $cd['contents'] ) ) {
				$contents = array();
				foreach ( $cd['contents'] as $content_data ) {
					$content = new \PYS_PRO_GLOBAL\FacebookAds\Object\ServerSide\Content();
					if ( isset( $content_data['product_id'] ) ) {
						$content->setProductId( $content_data['product_id'] );
					}
					if ( isset( $content_data['quantity'] ) ) {
						$content->setQuantity( $content_data['quantity'] );
					}
					if ( isset( $content_data['item_price'] ) ) {
						$content->setItemPrice( $content_data['item_price'] );
					}
					$contents[] = $content;
				}
				$custom_data->setContents( $contents );
			}

			// Set custom properties
			if ( isset( $cd['custom_properties'] ) && is_array( $cd['custom_properties'] ) ) {
				$custom_data->setCustomProperties( $cd['custom_properties'] );
			}

			$event->setCustomData( $custom_data );
		}

		// Set data processing options if LDU mode
		if ( isset( $server_event_data['data_processing_options'] ) ) {
			$event->setDataProcessingOptions( $server_event_data['data_processing_options'] );
			if ( isset( $server_event_data['data_processing_options_country'] ) ) {
				$event->setDataProcessingOptionsCountry( $server_event_data['data_processing_options_country'] );
			}
			if ( isset( $server_event_data['data_processing_options_state'] ) ) {
				$event->setDataProcessingOptionsState( $server_event_data['data_processing_options_state'] );
			}
		}

		return $event;
	}

	/**
	 * Send event directly to Facebook API
	 * Same logic as PurchaseEventManager::send_event_directly_to_api()
	 * Ensures customer data (IP, User Agent, fbp, fbc) is not overwritten by admin data
	 *
	 * @param array $pixel_ids
	 * @param \PYS_PRO_GLOBAL\FacebookAds\Object\ServerSide\Event $event
	 * @param array|null $saved_user_data Saved customer user data to prevent admin data overwrite
	 * @param int|null $order_id Order ID
	 */
	private function send_event_directly_to_api( $pixel_ids, $event, $saved_user_data = null, $order_id = null ) {
		if ( ! $event || apply_filters( 'pys_disable_server_event_filter', false ) ) {
			return;
		}

		// Get access tokens and test codes
		$access_token = Facebook()->getApiToken();
		$test_code = Facebook()->getApiTestCode();

		foreach ( $pixel_ids as $pixel_id ) {
			if ( empty( $access_token[ $pixel_id ] ) ) {
				continue;
			}

			$event->setEventId( $event->getEventId() );

			$api = Api::init( null, null, $access_token[ $pixel_id ], false );
			$opts = $api->getHttpClient()->getAdapter()->getOpts();
			if ( $opts instanceof \ArrayObject && $opts->offsetExists( CURLOPT_CONNECTTIMEOUT ) ) {
				$opts->offsetSet( CURLOPT_CONNECTTIMEOUT, 30 );
				$api->getHttpClient()->getAdapter()->setOpts( $opts );
			}

			// CRITICAL: Ensure saved customer data is used (not admin data)
			if ( $saved_user_data && is_array( $saved_user_data ) ) {
				$user_data = $event->getUserData();
				if ( ! $user_data ) {
					$user_data = new \PYS_PRO_GLOBAL\FacebookAds\Object\ServerSide\UserData();
				}

				// Ensure customer's IP address is used (saved at checkout time)
				if ( ! empty( $saved_user_data['client_ip_address'] ) ) {
					$user_data->setClientIpAddress( $saved_user_data['client_ip_address'] );
					error_log( '[CustomOrderStatusEventManager] Using saved customer IP: ' . $saved_user_data['client_ip_address'] );
				}

				// Ensure customer's User Agent is used (saved at checkout time)
				if ( ! empty( $saved_user_data['client_user_agent'] ) ) {
					$user_data->setClientUserAgent( $saved_user_data['client_user_agent'] );
					error_log( '[CustomOrderStatusEventManager] Using saved customer User Agent: ' . substr( $saved_user_data['client_user_agent'], 0, 50 ) . '...' );
				}

				// Ensure customer's fbp is used (saved at checkout time)
				if ( ! empty( $saved_user_data['fbp'] ) ) {
					$user_data->setFbp( $saved_user_data['fbp'] );
					error_log( '[CustomOrderStatusEventManager] Using saved customer fbp: ' . $saved_user_data['fbp'] );
				}

				// Ensure customer's fbc is used (saved at checkout time)
				if ( ! empty( $saved_user_data['fbc'] ) ) {
					$user_data->setFbc( $saved_user_data['fbc'] );
					error_log( '[CustomOrderStatusEventManager] Using saved customer fbc: ' . $saved_user_data['fbc'] );
				}

				// Set the user data back to event
				$event->setUserData( $user_data );
			}

			$request = ( new EventRequest( $pixel_id ) )->setEvents( [ $event ] );
			$request->setPartnerAgent( "dvorderflow" );
			if ( ! empty( $test_code[ $pixel_id ] ) ) {
				$request->setTestEventCode( $test_code[ $pixel_id ] );
			}

			PYS()->getLog()->debug( 'Send FB server event (custom status)', $request );
			try {
				$response = $request->execute();
				PYS()->getLog()->debug( 'Response from FB server (custom status)', $response );
			} catch ( \Exception $e ) {
				if ( $e instanceof RequestException ) {
					PYS()->getLog()->error( 'Error send FB server event (custom status) ' . $e->getErrorUserMessage(), $e->getResponse() );
				} else {
					PYS()->getLog()->error( 'Error send FB server event (custom status)', $e );
				}
			}
		}
	}
}

/**
 * @return Custom_Order_Status_Event_Manager
 */
function CustomOrderStatusEventManager() {
	return Custom_Order_Status_Event_Manager::instance();
}

// Initialize CustomOrderStatusEventManager - file is auto-loaded, just instantiate
CustomOrderStatusEventManager();

