<?php
/**
 * Checkout Funnel Tracker
 *
 * Records which checkout step each session reaches and exposes
 * a REST endpoint for the frontend JS to report step progress.
 *
 * Steps (in order):
 *  1. cart_viewed
 *  2. checkout_initiated
 *  3. billing_filled
 *  4. shipping_calculated
 *  5. payment_selected
 *  6. order_placed
 *
 * @package InsightPress
 */

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

class InsightPress_Funnel_Tracker
{
    const TABLE_NAME = 'insightpress_funnel_events';

    const STEPS = array(
        'cart_viewed',
        'checkout_initiated',
        'billing_filled',
        'shipping_calculated',
        'payment_selected',
        'order_placed',
    );

    public function __construct()
    {
        add_action('init', array($this, 'maybe_create_table'));

        // Enqueue frontend tracking JS on cart & checkout pages
        add_action('wp_enqueue_scripts', array($this, 'enqueue_tracking_script'));

        // Server-side: mark order_placed when an order is successfully created
        add_action('woocommerce_checkout_order_created',              array($this, 'record_order_placed'), 10, 1);
        add_action('woocommerce_store_api_checkout_order_processed',  array($this, 'record_order_placed'), 10, 1);

        // REST endpoint for JS to report steps
        add_action('rest_api_init', array($this, 'register_event_route'));
    }

    /**
     * Create DB table.
     */
    public function maybe_create_table()
    {
        global $wpdb;
        $table = $wpdb->prefix . self::TABLE_NAME;

        if ($wpdb->get_var("SHOW TABLES LIKE '$table'") === $table) {
            return;
        }

        $charset_collate = $wpdb->get_charset_collate();
        $sql = "CREATE TABLE $table (
            id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
            session_id VARCHAR(255) NOT NULL,
            step VARCHAR(100) NOT NULL,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (id),
            UNIQUE KEY session_step (session_id, step),
            KEY step (step),
            KEY created_at (created_at)
        ) $charset_collate;";

        require_once ABSPATH . 'wp-admin/includes/upgrade.php';
        dbDelta($sql);
    }

    /**
     * Get current session ID (mirrors the cart tracker logic).
     */
    protected function get_session_id()
    {
        if (is_user_logged_in()) {
            return 'user_' . get_current_user_id();
        }
        if (isset(WC()->session) && WC()->session->get_customer_id()) {
            return 'session_' . WC()->session->get_customer_id();
        }
        if (!session_id()) {
            @session_start();
        }
        return 'php_' . session_id();
    }

    /**
     * REST route: POST /insightpress/v1/funnel/event
     */
    public function register_event_route()
    {
        register_rest_route('insightpress/v1', '/funnel/event', array(
            'methods'             => 'POST',
            'callback'            => array($this, 'handle_event'),
            'permission_callback' => '__return_true', // Public – guarded by nonce in JS
        ));
    }

    /**
     * Handle an incoming step event from JS.
     */
    public function handle_event($request)
    {
        // Verify nonce
        $nonce = $request->get_header('X-WP-Nonce');
        if (!wp_verify_nonce($nonce, 'wp_rest')) {
            return new WP_Error('forbidden', 'Invalid nonce.', array('status' => 403));
        }

        $step = sanitize_key($request->get_param('step'));
        if (!in_array($step, self::STEPS, true)) {
            return new WP_Error('invalid_step', 'Unknown funnel step.', array('status' => 400));
        }

        $this->record_step($step);

        return rest_ensure_response(array('recorded' => true, 'step' => $step));
    }

    /**
     * Insert or ignore a step record for this session.
     */
    public function record_step($step)
    {
        global $wpdb;

        $session_id = $this->get_session_id();
        $table      = $wpdb->prefix . self::TABLE_NAME;

        // Use INSERT IGNORE so duplicate session+step combos are skipped
        $wpdb->query(
            $wpdb->prepare(
                "INSERT IGNORE INTO $table (session_id, step, created_at) VALUES (%s, %s, %s)",
                $session_id,
                $step,
                current_time('mysql')
            )
        );
    }

    /**
     * Server-side: record order_placed step.
     */
    public function record_order_placed($order)
    {
        $this->record_step('order_placed');
    }

    /**
     * Enqueue the JS that fires step events on cart/checkout pages.
     */
    public function enqueue_tracking_script()
    {
        if (!function_exists('is_cart') || !function_exists('is_checkout')) {
            return;
        }

        if (!is_cart() && !is_checkout()) {
            return;
        }

        // Pass the REST URL and nonce to JS
        $data = array(
            'apiUrl' => rest_url('insightpress/v1/'),
            'nonce'  => wp_create_nonce('wp_rest'),
        );

        wp_register_script('insightpress-funnel', false, array(), null, true);
        wp_enqueue_script('insightpress-funnel');
        wp_add_inline_script('insightpress-funnel', 'var insightPressFunnel = ' . wp_json_encode($data) . ';');

        $inline_js = "
(function() {
    if (typeof insightPressFunnel === 'undefined') return;

    var api   = insightPressFunnel.apiUrl;
    var nonce = insightPressFunnel.nonce;
    var sent  = {};

    function sendStep(step) {
        if (sent[step]) return;
        sent[step] = true;
        fetch(api + 'funnel/event', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-WP-Nonce': nonce
            },
            body: JSON.stringify({ step: step })
        }).catch(function(){});
    }

    // ── Step 1: Cart Viewed ─────────────────────────────
    if (document.body.classList.contains('woocommerce-cart')) {
        sendStep('cart_viewed');
    }

    // ── Step 2: Checkout Initiated ──────────────────────
    if (document.body.classList.contains('woocommerce-checkout')) {
        sendStep('checkout_initiated');

        // ── Step 3: Billing Details Filled ─────────────
        var billingFields = [
            '#billing_first_name', '#billing_last_name',
            '#billing_email', '#billing_phone'
        ];
        var billingFilled = false;
        function checkBilling() {
            if (billingFilled) return;
            var allFilled = billingFields.every(function(sel) {
                var el = document.querySelector(sel);
                return el && el.value.trim() !== '';
            });
            if (allFilled) {
                billingFilled = true;
                sendStep('billing_filled');
            }
        }
        billingFields.forEach(function(sel) {
            var el = document.querySelector(sel);
            if (el) el.addEventListener('blur', checkBilling);
        });

        // ── Step 4: Shipping Calculated ─────────────────
        // Fires when shipping method radio changes OR when update_checkout fires
        document.addEventListener('change', function(e) {
            if (e.target && e.target.name === 'shipping_method[0]') {
                sendStep('shipping_calculated');
            }
        });
        // WooCommerce triggers this jQuery event after shipping recalculation
        if (typeof jQuery !== 'undefined') {
            jQuery(document.body).on('updated_checkout', function() {
                sendStep('shipping_calculated');
            });
        }

        // ── Step 5: Payment Method Selected ────────────
        document.addEventListener('change', function(e) {
            if (e.target && e.target.name === 'payment_method') {
                sendStep('payment_selected');
            }
        });
        // Auto-fire if a payment method is already pre-selected
        var preSelected = document.querySelector('input[name=\"payment_method\"]:checked');
        if (preSelected) {
            setTimeout(function() { sendStep('payment_selected'); }, 800);
        }
    }

    // ── Step 6: Order Placed is handled server-side ─────
})();
";
        wp_add_inline_script('insightpress-funnel', $inline_js, 'after');
    }

    /**
     * Return the prefixed table name.
     */
    public static function get_table_name()
    {
        global $wpdb;
        return $wpdb->prefix . self::TABLE_NAME;
    }
}
