<?php

namespace orderflow\Facebook;

use orderflow\Traits\Courier;
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.
}

class PurchaseEventManager {
    use Courier;

    private static $_instance;

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

    public function __construct() {
        // Hook to save purchase event data when order is placed
        add_action( 'woocommerce_checkout_order_processed', array( $this, 'save_purchase_event_data' ), 20, 1 );

        // Hook to send purchase event when order status changes to ads-purchase
        add_action( 'woocommerce_order_status_changed', array( $this, 'send_purchase_event_on_status_change' ), 10, 3 );

    }

    /**
     * Save purchase event data when order is placed
     * Always saves data regardless of immediately send settings
     * This data is needed for custom status events even when purchase is sent immediately
     *
     * @param int $order_id
     */
    public function save_purchase_event_data( $order_id ) {
        error_log( '[PurchaseEventManager] save_purchase_event_data called for order_id: ' . $order_id );

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

        // Check if purchase event is enabled
        if ( ! Facebook()->getOption( 'of_woo_purchase_enabled' ) ) {
            error_log( '[PurchaseEventManager] Purchase event is disabled' );
            return;
        }

        // Always save event data (even when immediately sending)
        // This data is needed for custom status events
        error_log( '[PurchaseEventManager] Always saving purchase event data for order_id: ' . $order_id );

        // Generate and save purchase event data
        $this->generate_and_save_purchase_event_data( $order );
    }

    /**
     * Generate purchase event data and save to order meta
     * Uses the same method as normal purchase event generation
     * Same flow as completed_purchase() method - uses all the same classes and functions
     *
     * @param \WC_Order $order
     */
    private function generate_and_save_purchase_event_data( $order ) {
        error_log( '[PurchaseEventManager] Generating purchase event data for order_id: ' . $order->get_id() );

        // Set order key in request (needed for getWooPurchaseEventParams)
        $original_key = isset( $_REQUEST['key'] ) ? $_REQUEST['key'] : null;
        $_REQUEST['key'] = $order->get_order_key();

        // Set order ID filter (same as completed_purchase method)
        add_filter( "pys_woo_checkout_order_id", function() use ( $order ) {
            return $order->get_id();
        } );

        // Create SingleEvent - same as EventsWoo()->getEvent('woo_purchase')
        $single_event = new SingleEvent( 'woo_purchase', EventTypes::$STATIC, 'woo' );

        // Generate events using Facebook()->generateEvents() - same as normal purchase
        // This will automatically call addParamsToEvent() which calls getWooPurchaseEventParams()
        // All parameters including fbp, fbc, etc. will be added automatically
        $generated_events = Facebook()->generateEvents( $single_event );

        // Remove filter
        remove_all_filters( "pys_woo_checkout_order_id" );

        // Restore original key
        if ( $original_key !== null ) {
            $_REQUEST['key'] = $original_key;
        } else {
            unset( $_REQUEST['key'] );
        }

        if ( empty( $generated_events ) ) {
            error_log( '[PurchaseEventManager] Failed to generate Facebook events' );
            return;
        }

        // Get the first generated event (contains all parameters from getWooPurchaseEventParams)
        $generated_event = $generated_events[0];

        // Add landing page if available (customer's cookie, not admin)
        if ( isset( $_COOKIE['pys_landing_page'] ) ) {
            $generated_event->addParams( array( 'landing_page' => $_COOKIE['pys_landing_page'] ) );
        }

        // Now call mapEventToServerEvent() to generate complete server event object
        // This will add all data: user data, fbp, fbc, IP, User Agent, custom data, etc.
        $server_event = \orderflow\Facebook\ServerEventHelper::mapEventToServerEvent( $generated_event );

        if ( ! $server_event ) {
            error_log( '[PurchaseEventManager] Failed to generate server event object' );
            return;
        }

        // Extract all data from server event object to save
        $server_event_data = $this->extract_server_event_data( $server_event, $order );

        // Get event ID from payload
        $event_id = isset( $generated_event->payload['eventID'] ) ? $generated_event->payload['eventID'] : EventIdGenerator::guidv4();

        // Prepare data to save - save complete server event data
        $purchase_event_data = array(
            'event_id' => $event_id,
            'server_event_data' => $server_event_data, // Complete server event data ready to send
            'pixel_ids' => $generated_event->payload['pixelIds'], // Pixel IDs for sending
            'woo_order' => $order->get_id(),
            'event_time' => time(),
        );

        // Log purchase event data
        error_log( '[PurchaseEventManager] Purchase event data generated: ' . print_r( $purchase_event_data, true ) );

        // Save to order meta
        if ( isWooCommerceVersionGte( '3.0.0' ) ) {
            $order->update_meta_data( '_ads_purchase_event_data', $purchase_event_data );
            $order->save();
        } else {
            update_post_meta( $order->get_id(), '_ads_purchase_event_data', $purchase_event_data );
        }

        error_log( '[PurchaseEventManager] Purchase event data saved to order meta' );
    }

    /**
     * Extract all data from server event object for saving
     *
     * @param \PYS_PRO_GLOBAL\FacebookAds\Object\ServerSide\Event $server_event
     * @param \WC_Order $order
     * @return array
     */
    private function extract_server_event_data( $server_event, $order ) {
        $data = array();

        // Extract basic event properties
        $data['event_name'] = $server_event->getEventName();
        $data['event_time'] = $server_event->getEventTime();
        $data['event_id'] = $server_event->getEventId();
        $data['event_source_url'] = $server_event->getEventSourceUrl();
        $data['action_source'] = $server_event->getActionSource();

        // Extract user data
        $user_data = $server_event->getUserData();
        if ( $user_data ) {
            $user_data_array = array();

            // Get all user data properties
            $user_data_array['fbp'] = method_exists( $user_data, 'getFbp' ) ? $user_data->getFbp() : null;
            $user_data_array['fbc'] = method_exists( $user_data, 'getFbc' ) ? $user_data->getFbc() : null;
            $user_data_array['client_ip_address'] = method_exists( $user_data, 'getClientIpAddress' ) ? $user_data->getClientIpAddress() : null;
            $user_data_array['client_user_agent'] = method_exists( $user_data, 'getClientUserAgent' ) ? $user_data->getClientUserAgent() : null;
            $user_data_array['email'] = method_exists( $user_data, 'getEmail' ) ? $user_data->getEmail() : null;
            $user_data_array['phone'] = method_exists( $user_data, 'getPhone' ) ? $user_data->getPhone() : null;
            $user_data_array['first_name'] = method_exists( $user_data, 'getFirstName' ) ? $user_data->getFirstName() : null;
            $user_data_array['last_name'] = method_exists( $user_data, 'getLastName' ) ? $user_data->getLastName() : null;
            $user_data_array['city'] = method_exists( $user_data, 'getCity' ) ? $user_data->getCity() : null;
            $user_data_array['state'] = method_exists( $user_data, 'getState' ) ? $user_data->getState() : null;
            $user_data_array['zip_code'] = method_exists( $user_data, 'getZipCode' ) ? $user_data->getZipCode() : null;
            $user_data_array['country_code'] = method_exists( $user_data, 'getCountryCode' ) ? $user_data->getCountryCode() : null;
            $user_data_array['external_id'] = method_exists( $user_data, 'getExternalId' ) ? $user_data->getExternalId() : null;
            $user_data_array['fb_login_id'] = method_exists( $user_data, 'getFbLoginId' ) ? $user_data->getFbLoginId() : null;

            $data['user_data'] = $user_data_array;
        }

        // Extract custom data
        $custom_data = $server_event->getCustomData();
        if ( $custom_data ) {
            $custom_data_array = array();

            // Get custom data properties
            $custom_data_array['value'] = method_exists( $custom_data, 'getValue' ) ? $custom_data->getValue() : null;
            $custom_data_array['currency'] = method_exists( $custom_data, 'getCurrency' ) ? $custom_data->getCurrency() : null;
            $custom_data_array['content_type'] = method_exists( $custom_data, 'getContentType' ) ? $custom_data->getContentType() : null;
            $custom_data_array['content_ids'] = method_exists( $custom_data, 'getContentIds' ) ? $custom_data->getContentIds() : null;
            $custom_data_array['content_name'] = method_exists( $custom_data, 'getContentName' ) ? $custom_data->getContentName() : null;
            $custom_data_array['content_category'] = method_exists( $custom_data, 'getContentCategory' ) ? $custom_data->getContentCategory() : null;
            $custom_data_array['num_items'] = method_exists( $custom_data, 'getNumItems' ) ? $custom_data->getNumItems() : null;

            // Get contents array
            $contents = method_exists( $custom_data, 'getContents' ) ? $custom_data->getContents() : null;
            if ( $contents && is_array( $contents ) ) {
                $contents_array = array();
                foreach ( $contents as $content ) {
                    if ( is_object( $content ) ) {
                        $contents_array[] = array(
                            'product_id' => method_exists( $content, 'getProductId' ) ? $content->getProductId() : null,
                            'quantity' => method_exists( $content, 'getQuantity' ) ? $content->getQuantity() : null,
                            'item_price' => method_exists( $content, 'getItemPrice' ) ? $content->getItemPrice() : null,
                        );
                    }
                }
                $custom_data_array['contents'] = $contents_array;
            }

            // Get custom properties
            $custom_properties = method_exists( $custom_data, 'getCustomProperties' ) ? $custom_data->getCustomProperties() : null;
            if ( $custom_properties ) {
                $custom_data_array['custom_properties'] = $custom_properties;
            }

            $data['custom_data'] = $custom_data_array;
        }

        // Extract data processing options
        $data_processing_options = method_exists( $server_event, 'getDataProcessingOptions' ) ? $server_event->getDataProcessingOptions() : null;
        if ( $data_processing_options ) {
            $data['data_processing_options'] = $data_processing_options;
            $data['data_processing_options_country'] = method_exists( $server_event, 'getDataProcessingOptionsCountry' ) ? $server_event->getDataProcessingOptionsCountry() : null;
            $data['data_processing_options_state'] = method_exists( $server_event, 'getDataProcessingOptionsState' ) ? $server_event->getDataProcessingOptionsState() : null;
        }

        return $data;
    }

    /**
     * Recreate server event object from saved data
     *
     * @param array $server_event_data
     * @return \PYS_PRO_GLOBAL\FacebookAds\Object\ServerSide\Event|null
     */
    private function recreate_server_event_from_saved_data( $server_event_data ) {
        if ( empty( $server_event_data ) ) {
            return null;
        }

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

        // Set basic properties
        if ( isset( $server_event_data['event_name'] ) ) {
            $event->setEventName( $server_event_data['event_name'] );
        }
        if ( isset( $server_event_data['event_time'] ) ) {
            $event->setEventTime( $server_event_data['event_time'] );
        }
        if ( isset( $server_event_data['event_id'] ) ) {
            $event->setEventId( $server_event_data['event_id'] );
        }
        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
        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
        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( $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 purchase event when order status changes to ads-purchase
     *
     * @param int $order_id
     * @param string $old_status
     * @param string $new_status
     */
    public function send_purchase_event_on_status_change( $order_id, $old_status, $new_status ) {
        error_log( '[PurchaseEventManager] send_purchase_event_on_status_change 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( '[PurchaseEventManager] Normalized new status: ' . $new_status );

        // Only process if status changed to ads-purchase
        if ( $new_status !== 'ads-purchase' ) {
            error_log( '[PurchaseEventManager] Status is not ads-purchase, skipping' );
            return;
        }

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

        // Check if purchase event is enabled
        if ( ! Facebook()->getOption( 'of_woo_purchase_enabled' ) ) {
            error_log( '[PurchaseEventManager] Purchase event is disabled' );
            return;
        }

        // Check if event was already sent successfully by verifying results
        $existing_results = null;
        if ( isWooCommerceVersionGte( '3.0.0' ) ) {
            $existing_results = $order->get_meta( 'ads_purchase_event_results', true );
        } else {
            $existing_results = get_post_meta( $order_id, 'ads_purchase_event_results', true );
        }
        
        // If results exist and show success, event was already sent
        if ( is_array( $existing_results ) && ! empty( $existing_results ) ) {
            $first_result = $existing_results[0];
            if ( isset( $first_result['response'] ) && $first_result['response'] === 'success' ) {
                error_log( '[PurchaseEventManager] Purchase event already sent successfully for order_id: ' . $order_id . '. Results found: ' . count( $existing_results ) );
                return;
            }
        }

        // Get saved purchase event data
        $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_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( '[PurchaseEventManager] No saved purchase event data found for order_id: ' . $order_id . '. Cannot generate now as it would use admin fbp/fbc instead of customer data. Event will not be sent.' );
            return;
        }

        error_log( '[PurchaseEventManager] Using saved purchase event data for order_id: ' . $order_id );

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

        // Recreate server event object from saved data (no need to call mapEventToServerEvent again)
        $server_event = $this->recreate_server_event_from_saved_data( $purchase_event_data['server_event_data'] );

        if ( ! $server_event ) {
            error_log( '[PurchaseEventManager] Failed to recreate server event from saved data' );
            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( '[PurchaseEventManager] No pixel IDs found in 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 (same logic as sendEvent method, but using saved data)
        // This avoids calling sendEvent which might use admin data
        if ( Facebook()->isServerApiEnabled() ) {
            $this->send_event_directly_to_api( $pixel_ids, $server_event, $saved_user_data, $order_id );
            error_log( '[PurchaseEventManager] Purchase event sent directly to Facebook API using saved server event data' );
        }

        // Mark event as fired (same as normal purchase)
        if ( isWooCommerceVersionGte( '3.0.0' ) ) {
            $order->update_meta_data( '_pys_purchase_event_fired', true );
            $order->save();
        } else {
            update_post_meta( $order_id, '_pys_purchase_event_fired', true );
        }

        error_log( '[PurchaseEventManager] Purchase event sent and marked as fired for order_id: ' . $order_id );
    }

    /**
     * Save purchase event results to order meta
     * 
     * @param string $pixel_id
     * @param \PYS_PRO_GLOBAL\FacebookAds\Object\ServerSide\Event $event
     * @param mixed $response
     * @param int|null $order_id Order ID (passed from calling function)
     */
    private function save_purchase_event_results_for_order( $pixel_id, $event, $response, $order_id = null ) {
        // Get order ID from parameter or from event custom properties
        if ( empty( $order_id ) ) {
            $custom_data = $event->getCustomData();
            if ( $custom_data ) {
                $custom_properties = method_exists( $custom_data, 'getCustomProperties' ) ? $custom_data->getCustomProperties() : null;
                if ( $custom_properties && isset( $custom_properties['woo_order'] ) ) {
                    $order_id = $custom_properties['woo_order'];
                }
            }
        }

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

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

        // Get existing results or create new array
        $existing_results = null;
        if ( isWooCommerceVersionGte( '3.0.0' ) ) {
            $existing_results = $order->get_meta( 'ads_purchase_event_results', true );
        } else {
            $existing_results = get_post_meta( $order_id, 'ads_purchase_event_results', true );
        }

        if ( ! is_array( $existing_results ) ) {
            $existing_results = [];
        }

        // Check if result for this pixel already exists
        $result_index = -1;
        foreach ( $existing_results as $index => $result ) {
            if ( isset( $result['pixel_id'] ) && $result['pixel_id'] === $pixel_id ) {
                $result_index = $index;
                break;
            }
        }

        // Prepare result data
        $result_data = array(
            'event_name' => 'Purchase',
            'pixel_id' => $pixel_id,
            'event_id' => $event->getEventId(),
            'sent_at' => time(),
            'response' => $response ? 'success' : 'failed',
        );

        // Increment sent_count if result exists, otherwise set to 1
        if ( $result_index >= 0 ) {
            $existing_results[ $result_index ]['sent_count'] = isset( $existing_results[ $result_index ]['sent_count'] ) 
                ? $existing_results[ $result_index ]['sent_count'] + 1 
                : 1;
            $existing_results[ $result_index ]['sent_at'] = time();
            $existing_results[ $result_index ]['response'] = $response ? 'success' : 'failed';
        } else {
            $result_data['sent_count'] = 1;
            $existing_results[] = $result_data;
        }

        // Save to order meta
        if ( isWooCommerceVersionGte( '3.0.0' ) ) {
            $order->update_meta_data( 'ads_purchase_event_results', $existing_results );
            $order->save();
        } else {
            update_post_meta( $order_id, 'ads_purchase_event_results', $existing_results );
        }

        error_log( '[PurchaseEventManager] Purchase event results saved for order_id: ' . $order_id . ', pixel_id: ' . $pixel_id );
    }

    /**
     * Send event directly to Facebook API
     * Same logic as FacebookServer::sendEvent() but uses saved data
     * 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 for purchase event result tracking
     */
    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)
            // The event object already contains saved customer data from recreate_server_event_from_saved_data()
            // But we double-check to ensure customer data is set correctly
            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( '[PurchaseEventManager] 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( '[PurchaseEventManager] 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( '[PurchaseEventManager] 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( '[PurchaseEventManager] 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', $request );
            try {
                $response = $request->execute();
                PYS()->getLog()->debug( 'Response from FB server', $response );
                
                // Save purchase event results
                $this->save_purchase_event_results_for_order( $pixel_id, $event, $response, $order_id );
            } catch ( \Exception $e ) {
                if ( $e instanceof RequestException ) {
                    PYS()->getLog()->error( 'Error send FB server event ' . $e->getErrorUserMessage(), $e->getResponse() );
                } else {
                    PYS()->getLog()->error( 'Error send FB server event', $e );
                }
            }
        }
    }


}

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

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

