<?php

namespace fluXtore\Core\Frontend;

use fluXtore\Core\Settings\fluXtore_Facebook_Pixel_Settings;
use fluXtore\Core\Settings\fluXtore_Settings;

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

if ( ! class_exists( 'fluXtore_Facebook_Pixel' ) ) {
        class fluXtore_Facebook_Pixel {
                /**
                 * @var self|null
                 */
                private static $instance = null;

                /**
                 * @var string
                 */
                private $pixel_id = '';

                /**
                 * @var array
                 */
                private $events = [];

                /**
                 * @var array
                 */
                private $config = [];

                /**
                 * @var array<int,bool>
                 */
                private $processed_orders = [];

                /**
                 * @var bool
                 */
                private $has_rendered = false;

                private function __construct() {}

                public static function init() {
                        if ( null !== self::$instance ) {
                                return;
                        }

                        self::$instance = new self();
                        self::$instance->register_hooks();
                }

                private function register_hooks() {
                        add_action( 'wp_head', [ $this, 'render_pixel' ] );
                        add_action( 'woocommerce_thankyou', [ $this, 'output_purchase_event' ], 20, 1 );
                }

                public function render_pixel() {
                        if ( $this->has_rendered ) {
                                return;
                        }

                        if ( is_admin() || ( function_exists( 'wp_doing_ajax' ) && wp_doing_ajax() ) ) {
                                return;
                        }

                        if ( $this->is_builder_preview() ) {
                                return;
                        }

                        $this->pixel_id = $this->get_pixel_id();

                        if ( '' === $this->pixel_id ) {
                                return;
                        }

                        if ( ! $this->is_relevant_context() ) {
                                return;
                        }

                        $this->events = $this->get_events_config();

                        $config       = $this->build_config();
                        $config       = apply_filters( 'fluxtore_facebook_pixel_config', $config );
                        $this->config = $config;

                        $this->has_rendered = true;

                        $should_track_checkout = ! empty( $config['events']['initiate_checkout'] ) && $this->is_checkout_context( $config['step']['tag'] ?? null );
                        $should_track_pageview = ! empty( $config['events']['page_view'] );

                        $pixel_id = esc_js( $this->pixel_id );
                        $config_json = wp_json_encode( $config );

                        ?>
<!-- fluXtore Facebook Pixel -->
<script>
if (!window.fbq) {
    !function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
    n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
    n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
    t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s);
    }(window, document,'script','https://connect.facebook.net/en_US/fbevents.js');
}
fbq('init', '<?php echo $pixel_id; ?>');
<?php if ( $should_track_pageview ) : ?>
fbq('track', 'PageView');
<?php endif; ?>
<?php if ( $should_track_checkout ) : ?>
fbq('track', 'InitiateCheckout');
<?php endif; ?>
window.fluxtoreFacebookPixel = Object.assign({}, window.fluxtoreFacebookPixel || {}, <?php echo $config_json; ?>);
</script>
<!-- End fluXtore Facebook Pixel -->
                        <?php

                        do_action( 'fluxtore_facebook_pixel_rendered', $config );
                }

                public function output_purchase_event( $order_id ) {
                        if ( empty( $order_id ) ) {
                                return;
                        }

                        if ( function_exists( 'wp_doing_ajax' ) && wp_doing_ajax() ) {
                                return;
                        }

                        if ( isset( $this->processed_orders[ $order_id ] ) ) {
                                return;
                        }

                        $this->processed_orders[ $order_id ] = true;

                        $this->events = ! empty( $this->events ) ? $this->events : $this->get_events_config();

                        if ( empty( $this->events['purchase'] ) ) {
                                return;
                        }

                        $this->pixel_id = '' !== $this->pixel_id ? $this->pixel_id : $this->get_pixel_id();

                        if ( '' === $this->pixel_id ) {
                                return;
                        }

                        $order = wc_get_order( $order_id );

                        if ( ! $order instanceof \WC_Order ) {
                                return;
                        }

                        $value    = (float) $order->get_total();
                        $currency = $order->get_currency();

                        $contents     = [];
                        $content_ids  = [];
                        $order_items  = fluXtore_Tracking_Helper::get_order_items( $order );

                        foreach ( $order_items as $item ) {
                                $product_id = isset( $item['product_id'] ) ? $item['product_id'] : ( $item['id'] ?? null );

                                if ( empty( $product_id ) ) {
                                        continue;
                                }

                                $quantity = isset( $item['quantity'] ) ? (int) $item['quantity'] : 0;

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

                                $product_id   = (string) $product_id;
                                $content_ids[] = $product_id;
                                $contents[]    = [
                                        'id'       => $product_id,
                                        'quantity' => $quantity,
                                ];
                        }

                        $payload = [
                                'value'    => $value,
                                'currency' => $currency,
                        ];

                        if ( ! empty( $contents ) ) {
                                $payload['contents']     = $contents;
                                $payload['content_type'] = 'product';
                        }

                        if ( ! empty( $content_ids ) ) {
                                $payload['content_ids'] = $content_ids;
                        }

                        $payload = apply_filters( 'fluxtore_facebook_pixel_purchase_payload', $payload, $order );

                        $json_payload = wp_json_encode( $payload );

                        ?>
<script>
if (window.fbq) {
    fbq('track', 'Purchase', <?php echo $json_payload; ?>);
}
</script>
                        <?php
                }

                private function get_pixel_id() {
                        $value = fluXtore_Settings::get( fluXtore_Facebook_Pixel_Settings::OPTION_PIXEL_ID, '' );

                        return is_string( $value ) ? trim( $value ) : '';
                }

                private function get_events_config() {
                        return [
                                'page_view'        => $this->get_flag( fluXtore_Facebook_Pixel_Settings::OPTION_PAGE_VIEW, true ),
                                'initiate_checkout'=> $this->get_flag( fluXtore_Facebook_Pixel_Settings::OPTION_INITIATE_CHECKOUT, true ),
                                'purchase'         => $this->get_flag( fluXtore_Facebook_Pixel_Settings::OPTION_PURCHASE, true ),
                                'order_bump'       => $this->get_flag( fluXtore_Facebook_Pixel_Settings::OPTION_ORDER_BUMP, true ),
                                'upsell_accept'    => $this->get_flag( fluXtore_Facebook_Pixel_Settings::OPTION_UPSELL_ACCEPT, true ),
                                'upsell_decline'   => $this->get_flag( fluXtore_Facebook_Pixel_Settings::OPTION_UPSELL_DECLINE, true ),
                        ];
                }

                private function build_config() {
                        return [
                                'id'       => $this->pixel_id,
                                'events'   => $this->events,
                                'step'     => fluXtore_Tracking_Helper::get_step_context(),
                                'currency' => fluXtore_Tracking_Helper::get_currency(),
                        ];
                }

                private function get_currency() {
                        return fluXtore_Tracking_Helper::get_currency();
                }

                private function is_checkout_context( $step_tag ) {
                        return fluXtore_Tracking_Helper::is_checkout_context( $step_tag );
                }

                private function is_builder_preview() {
                        return fluXtore_Tracking_Helper::is_builder_preview();
                }

                private function is_relevant_context() {
                        return fluXtore_Tracking_Helper::is_relevant_context();
                }

                private function get_flag( $option, $default = false ) {
                        $raw = fluXtore_Settings::get( $option, $default ? '1' : '0' );

                        if ( is_bool( $raw ) ) {
                                return $raw;
                        }

                        if ( is_numeric( $raw ) ) {
                                return (bool) intval( $raw );
                        }

                        if ( is_string( $raw ) ) {
                                $raw = trim( $raw );

                                if ( '' === $raw ) {
                                        return (bool) $default;
                                }

                                $filtered = filter_var( $raw, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE );

                                if ( null !== $filtered ) {
                                        return $filtered;
                                }
                        }

                        return (bool) $default;
                }
        }
}

fluXtore_Facebook_Pixel::init();
