<?php
/**
 * Plugin Name: ActiveTrail for WooCommerce
 * Plugin URI: https://wordpress.org/plugins/activetrail-for-woocommerce/
 * Description: Integrate WooCommerce store with ActiveTrail API for marketing automation, customer sync, and dynamic coupons.
 * Version: 1.2.4
 * Author: ActiveTrail
 * Author URI: https://www.activetrail.com
 * Text Domain: activetrail-for-woocommerce
 * Domain Path: /languages
 * Requires at least: 6.0
 * Tested up to: 6.9
 * Requires PHP: 7.4
 * Requires Plugins: woocommerce
 * WC requires at least: 6.0
 * WC tested up to: 9.0
 * WC HPOS Compatible: true
 * License: GPL v2 or later
 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
 */


// Prevent direct access.
if (!defined('ABSPATH')) {
    exit;
}

// Define plugin constants.
define('ACTIVETRAIL_WC_VERSION', '1.2.4');
define('ACTIVETRAIL_WC_PLUGIN_FILE', __FILE__);
define('ACTIVETRAIL_WC_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('ACTIVETRAIL_WC_PLUGIN_URL', plugin_dir_url(__FILE__));
define('ACTIVETRAIL_WC_PLUGIN_BASENAME', plugin_basename(__FILE__));

/**
 * Declare HPOS (High-Performance Order Storage) compatibility.
 *
 * WooCommerce determines compatibility via this runtime declaration, not the
 * "WC HPOS Compatible" plugin header. Must run on 'before_woocommerce_init'.
 */
add_action('before_woocommerce_init', function () {
    if (class_exists(\Automattic\WooCommerce\Utilities\FeaturesUtil::class)) {
        \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
            'custom_order_tables',
            __FILE__,
            true
        );
    }
});

/**
 * Sanitize array data recursively after json_decode
 *
 * @param mixed $data Data to sanitize.
 * @return mixed Sanitized data.
 */
function activetrail_wc_sanitize_array($data) {
    if (is_array($data)) {
        $sanitized = array();
        foreach ($data as $key => $value) {
            $key = sanitize_key($key);
            if (is_array($value)) {
                $sanitized[$key] = activetrail_wc_sanitize_array($value);
            } elseif (is_string($value)) {
                // Use sanitize_text_field for strings, but preserve email format if it's an email field.
                if (filter_var($value, FILTER_VALIDATE_EMAIL)) {
                    $sanitized[$key] = sanitize_email($value);
                } elseif (filter_var($value, FILTER_VALIDATE_URL)) {
                    $sanitized[$key] = esc_url_raw($value);
                } else {
                    $sanitized[$key] = sanitize_text_field($value);
                }
            } elseif (is_numeric($value)) {
                $sanitized[$key] = is_float($value) ? floatval($value) : intval($value);
            } elseif (is_bool($value)) {
                $sanitized[$key] = (bool) $value;
            } else {
                $sanitized[$key] = sanitize_text_field(strval($value));
            }
        }
        return $sanitized;
    }
    return $data;
}

/**
 * Generate external ID for ActiveTrail
 *
 * @param string $type Entity type (contact, order, cart)
 * @param string|int $id Entity ID
 * @return string
 */
function activetrail_generate_external_id($type, $id) {
    $type = strtoupper((string) $type);
    $id = (string) $id;
    return "WC-{$type}-{$id}";
}

/**
 * Generate external ID for contact
 *
 * @param int $user_id User ID (0 for guest)
 * @param string $email Email address (for guest)
 * @return string
 */
function activetrail_external_id_for_contact($user_id = 0, $email = '') {
    if ($user_id) return activetrail_generate_external_id('CONTACT', $user_id);
    if ($email) return activetrail_generate_external_id('CONTACT', 'GUEST-' . md5(strtolower(trim($email))));
    return activetrail_generate_external_id('CONTACT', 'GUEST-UNKNOWN');
}

/**
 * Generate external ID for order
 *
 * @param int $order_id Order ID
 * @return string
 */
function activetrail_external_id_for_order($order_id) {
    return activetrail_generate_external_id('ORDER', $order_id);
}

/**
 * Generate external ID for cart
 *
 * @param string|int $key_or_user Cart key or user ID
 * @return string
 */
function activetrail_external_id_for_cart($key_or_user) {
    return activetrail_generate_external_id('CART', $key_or_user);
}

// Define external name constant.
if (!defined('ACTIVETRAIL_EXTERNAL_NAME')) {
    define('ACTIVETRAIL_EXTERNAL_NAME', 'WooCommerce');
}

/**
 * Check if WooCommerce is active
 */
function activetrail_wc_check_woocommerce() {
    if (!class_exists('WooCommerce')) {
        add_action('admin_notices', 'activetrail_wc_missing_woocommerce_notice');
        return false;
    }
    return true;
}

/**
 * Display notice if WooCommerce is not active
 */
function activetrail_wc_missing_woocommerce_notice() {
    ?>
    <div class="notice notice-error">
        <p><?php 
        // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch -- Text domain 'activetrail-for-woocommerce' is correct per WordPress review requirements
        esc_html_e('ActiveTrail for WooCommerce requires WooCommerce to be installed and active.', 'activetrail-for-woocommerce'); ?></p>
    </div>
    <?php
}

/**
 * Initialize the plugin
 */
function activetrail_wc_init() {
    // Check if WooCommerce is active.
    if (!activetrail_wc_check_woocommerce()) {
        return;
    }

    // Load the logger class first.
    require_once ACTIVETRAIL_WC_PLUGIN_DIR . 'includes/class-activetrail-logger.php';
    
    // Load the main plugin class.
    require_once ACTIVETRAIL_WC_PLUGIN_DIR . 'includes/class-activetrail-plugin.php';
    
    // Debug class is not loaded in production.
    
    // Initialize the plugin.
    ActiveTrail_Plugin::get_instance();
}

/**
 * Load plugin text domain for translations
 * Must be called on 'init' hook or later to avoid triggering WooCommerce translations too early
 */
function activetrail_wc_load_textdomain() {
    // Load settings to get current language.
    require_once ACTIVETRAIL_WC_PLUGIN_DIR . 'includes/settings/class-settings.php';
    $current_language = ActiveTrail_Settings::get_current_language();
    
    // Set locale based on plugin setting.
    add_filter('locale', function($locale) use ($current_language) {
        // Only override locale for our plugin's admin pages.
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Navigation only, no data processing
        if (is_admin() && isset($_GET['tab']) && sanitize_text_field(wp_unslash($_GET['tab'])) === 'activetrail') {
            return $current_language;
        }
        return $locale;
    });
    
    // Load plugin text domain.
    $domain = 'activetrail-for-woocommerce';
    $locale = $current_language;
    
    // Try to load from plugin languages directory first.
    // Note: MO files are named activetrail-woocommerce-{locale}.mo.
    $mofile = ACTIVETRAIL_WC_PLUGIN_DIR . 'languages/activetrail-woocommerce-' . $locale . '.mo';
    if (file_exists($mofile)) {
        // Unload existing text domain first to force reload with new language.
        unload_textdomain($domain);
        load_textdomain($domain, $mofile);
        return;
    }
    
    // Fallback to WordPress languages directory.
    $mofile = WP_LANG_DIR . '/plugins/activetrail-woocommerce-' . $locale . '.mo';
    if (file_exists($mofile)) {
        // Unload existing text domain first to force reload with new language.
        unload_textdomain($domain);
        load_textdomain($domain, $mofile);
        return;
    }
    
    // If the specific language file doesn't exist, don't load any translation.
    // This prevents fallback to wrong language.
    return;
}

// Hook into plugins_loaded to ensure WooCommerce is loaded first.
add_action('plugins_loaded', 'activetrail_wc_init');

// Load text domain on 'init' hook to avoid triggering WooCommerce translations too early.
add_action('init', 'activetrail_wc_load_textdomain', 1);

/**
 * Map ActiveTrail discount types to WooCommerce values
 *
 * @param string $type
 * @return string
 */
function activetrail_wc_map_discount_type($type) {
    $type_map = array(
        'percentage' => 'percent',
        'fixed_price' => 'fixed_cart',
        'free_shipping' => 'fixed_cart',
        'percent' => 'percent',
        'fixed_cart' => 'fixed_cart',
        'fixed_product' => 'fixed_product',
    );

    return $type_map[$type] ?? $type;
}

/**
 * Normalize coupon payloads coming from ActiveTrail (camelCase → snake_case)
 *
 * @param array $payload
 * @return array
 */
function activetrail_wc_normalize_coupon_payload($payload) {
    if (!is_array($payload) || empty($payload)) {
        return $payload;
    }

    $field_map = array(
        'couponCode' => 'coupon_code',
        'discountType' => 'discount_type',
        'amount' => 'amount',
        'description' => 'description',
        'expiryDate' => 'date_expires',
        'minCartValue' => 'minimum_amount',
        'maxCartValue' => 'maximum_amount',
        'individualUse' => 'individual_use',
        'usageLimit' => 'usage_limit',
        'usageLimitPerUser' => 'usage_limit_per_user',
        'freeShipping' => 'free_shipping',
        'excludeSaleItems' => 'exclude_sale_items',
        'productIds' => 'product_ids',
        'excludedProductIds' => 'excluded_product_ids',
        'productCategories' => 'product_categories',
        'excludedProductCategories' => 'excluded_product_categories',
        'emailRestrictions' => 'email_restrictions',
        'externalId' => 'external_id',
        'accountId' => 'account_id',
    );

    $normalized = $payload;
    $converted = false;

    foreach ($field_map as $camel => $snake) {
        if (array_key_exists($camel, $payload) && (!array_key_exists($snake, $normalized) || $normalized[$snake] === '')) {
            $normalized[$snake] = $payload[$camel];
            $converted = true;
        }
    }

    if ($converted && isset($normalized['discount_type'])) {
        $normalized['discount_type'] = activetrail_wc_map_discount_type($normalized['discount_type']);
    }

    $incoming_discount_type = $payload['discountType'] ?? '';
    if ($incoming_discount_type === 'free_shipping') {
        $normalized['free_shipping'] = true;
        $normalized['discount_type'] = 'fixed_cart';
        if (!isset($normalized['amount']) || $normalized['amount'] === '') {
            $normalized['amount'] = '0';
        }
    }

    return $normalized;
}

/**
 * Handle ActiveTrail coupon creation requests
 */
function activetrail_wc_handle_coupon_request() {
    // Check if this is a coupon creation request.
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- External webhook endpoint, authentication handled separately
    if (!isset($_GET['activetrail_coupon']) || sanitize_text_field(wp_unslash($_GET['activetrail_coupon'])) !== 'create') {
        return;
    }
    
    // Ensure WooCommerce is fully loaded.
    if (!function_exists('wc_get_product')) {
        if (class_exists('WooCommerce')) {
            WC();
        } else {
            wp_die('WooCommerce is not available', 'ActiveTrail Coupon Error', array('response' => 500));
        }
    }
    
    // Initialize logger if available.
    $logger = function_exists('activetrail_logger') ? activetrail_logger() : null;
    
    if ($logger) {
        $logger->product_feed('🚀 ActiveTrail coupon creation request received', ActiveTrail_Logger::LEVEL_INFO, array(
            'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])) : 'unknown',
            'ip' => isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : 'unknown',
            'request_uri' => isset($_SERVER['REQUEST_URI']) ? esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'])) : 'unknown'
        ));
    }
    
    // Check if request method is POST.
    $request_method = isset($_SERVER['REQUEST_METHOD']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_METHOD'])) : '';
    if ($request_method !== 'POST') {
        if ($logger) {
            $logger->product_feed('❌ Invalid request method for coupon creation', ActiveTrail_Logger::LEVEL_ERROR, array(
                'method' => $request_method
            ));
        }
        wp_die('Method not allowed', 'ActiveTrail Coupon Error', array('response' => 405));
    }
    
    // Get the request body.
    $input = file_get_contents('php://input');
    $data = json_decode($input, true);
    
    if (!$data) {
        if ($logger) {
            $logger->product_feed('❌ Invalid JSON data received', ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die('Invalid JSON data', 'ActiveTrail Coupon Error', array('response' => 400));
    }

    // Sanitize decoded data.
    $data = activetrail_wc_sanitize_array($data);
    $data = activetrail_wc_normalize_coupon_payload($data);
    
    // Validate required fields.
    $requires_amount = empty($data['free_shipping']);
    $required_fields = array('coupon_code', 'discount_type');
    foreach ($required_fields as $field) {
        if (empty($data[$field])) {
            if ($logger) {
                $logger->product_feed('❌ Missing required field: ' . $field, ActiveTrail_Logger::LEVEL_ERROR);
            }
            wp_die(esc_html('Missing required field: ' . $field), 'ActiveTrail Coupon Error', array('response' => 400));
        }
    }
    if ($requires_amount && empty($data['amount'])) {
        if ($logger) {
            $logger->product_feed('❌ Missing required field: amount', ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die('Missing required field: amount', 'ActiveTrail Coupon Error', array('response' => 400));
    } elseif (!$requires_amount && !isset($data['amount'])) {
        $data['amount'] = '0';
    }
    
    // Validate discount type.
    $valid_types = array('percent', 'fixed_cart', 'fixed_product');
    if (!in_array($data['discount_type'], $valid_types)) {
        if ($logger) {
            $logger->product_feed('❌ Invalid discount type: ' . $data['discount_type'], ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die(esc_html('Invalid discount_type. Must be one of: ' . implode(', ', $valid_types)), 'ActiveTrail Coupon Error', array('response' => 400));
    }
    
    if ($requires_amount) {
        $amount = floatval($data['amount']);
        if ($amount <= 0) {
            if ($logger) {
                $logger->product_feed('❌ Invalid amount: ' . $data['amount'], ActiveTrail_Logger::LEVEL_ERROR);
            }
            wp_die('Amount must be greater than 0', 'ActiveTrail Coupon Error', array('response' => 400));
        }
        
        if ($data['discount_type'] === 'percent' && $amount > 100) {
            if ($logger) {
                $logger->product_feed('❌ Percent amount cannot exceed 100: ' . $data['amount'], ActiveTrail_Logger::LEVEL_ERROR);
            }
            wp_die('Percent amount cannot exceed 100', 'ActiveTrail Coupon Error', array('response' => 400));
        }
    } else {
        $data['amount'] = '0';
    }
    
    // Check for existing coupon by external_id (idempotency).
    if (!empty($data['external_id'])) {
        $existing_coupon_id = activetrail_wc_find_coupon_by_external_id($data['external_id']);
        if ($existing_coupon_id) {
            // Update existing coupon.
            $result = activetrail_wc_update_coupon($existing_coupon_id, $data);
            if ($result['success']) {
                if ($logger) {
                    $logger->product_feed('✅ Coupon updated successfully: ' . $data['coupon_code'] . ' (ID: ' . $existing_coupon_id . ')', ActiveTrail_Logger::LEVEL_INFO);
                }
                wp_send_json($result, 200);
            } else {
                if ($logger) {
                    $logger->product_feed('❌ Failed to update coupon: ' . $result['message'], ActiveTrail_Logger::LEVEL_ERROR);
                }
                wp_send_json($result, 500);
            }
        }
    }
    
    // Check if coupon code already exists (without external_id).
    if (empty($data['external_id'])) {
        $existing_coupon_id = wc_get_coupon_id_by_code($data['coupon_code']);
        if ($existing_coupon_id) {
            if ($logger) {
                $logger->product_feed('❌ Coupon code already exists without external_id: ' . $data['coupon_code'], ActiveTrail_Logger::LEVEL_ERROR);
            }
            wp_send_json(array(
                'success' => false,
                'message' => 'Coupon code already exists. Use external_id for idempotency.'
            ), 409);
        }
    }
    
    // Create new coupon.
    $result = activetrail_wc_create_coupon($data);
    
    if ($result['success']) {
        if ($logger) {
            $logger->product_feed('✅ Coupon created successfully: ' . $result['coupon_code'] . ' (ID: ' . $result['coupon_id'] . ')', ActiveTrail_Logger::LEVEL_INFO);
        }
        wp_send_json($result, 201);
    } else {
        if ($logger) {
            $logger->product_feed('❌ Failed to create coupon: ' . $result['message'], ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_send_json($result, 500);
    }
}

/**
 * Create WooCommerce coupon
 */
function activetrail_wc_create_coupon($coupon_data) {
    try {
        // Generate unique code if not provided.
        if (empty($coupon_data['coupon_code'])) {
            $prefix = $coupon_data['prefix'] ?? 'AT';
            $coupon_data['coupon_code'] = activetrail_wc_generate_unique_code($prefix);
        }
        
        // Create new coupon.
        $coupon = new WC_Coupon();
        
        // Set basic properties.
        $coupon->set_code($coupon_data['coupon_code']);
        $coupon->set_discount_type($coupon_data['discount_type']);
        $coupon->set_amount(floatval($coupon_data['amount']));
        
        // Set description.
        if (!empty($coupon_data['description'])) {
            $coupon->set_description($coupon_data['description']);
        }
        
        // Set expiry date.
        if (!empty($coupon_data['date_expires'])) {
            $coupon->set_date_expires($coupon_data['date_expires']);
        }
        
        // Set usage limits.
        if (isset($coupon_data['usage_limit']) && $coupon_data['usage_limit'] > 0) {
            $coupon->set_usage_limit($coupon_data['usage_limit']);
        }
        
        if (isset($coupon_data['usage_limit_per_user']) && $coupon_data['usage_limit_per_user'] > 0) {
            $coupon->set_usage_limit_per_user($coupon_data['usage_limit_per_user']);
        }
        
        // Set amount limits.
        if (!empty($coupon_data['minimum_amount'])) {
            $coupon->set_minimum_amount(floatval($coupon_data['minimum_amount']));
        }
        
        if (!empty($coupon_data['maximum_amount'])) {
            $coupon->set_maximum_amount(floatval($coupon_data['maximum_amount']));
        }
        
        // Set boolean properties.
        if (isset($coupon_data['individual_use'])) {
            $coupon->set_individual_use($coupon_data['individual_use']);
        }
        
        if (isset($coupon_data['free_shipping'])) {
            $coupon->set_free_shipping($coupon_data['free_shipping']);
        }
        
        // Set product restrictions.
        if (!empty($coupon_data['product_ids'])) {
            $coupon->set_product_ids($coupon_data['product_ids']);
        }
        
        if (!empty($coupon_data['excluded_product_ids'])) {
            $coupon->set_excluded_product_ids($coupon_data['excluded_product_ids']);
        }
        
        if (!empty($coupon_data['product_categories'])) {
            $coupon->set_product_categories($coupon_data['product_categories']);
        }
        
        if (!empty($coupon_data['excluded_product_categories'])) {
            $coupon->set_excluded_product_categories($coupon_data['excluded_product_categories']);
        }
        
        // Set email restrictions.
        if (!empty($coupon_data['email_restrictions'])) {
            $coupon->set_email_restrictions($coupon_data['email_restrictions']);
        }
        
        // Save coupon.
        $coupon_id = $coupon->save();
        
        if (!$coupon_id) {
            return array(
                'success' => false,
                'message' => 'Failed to save coupon'
            );
        }
        
        // Mark as ActiveTrail coupon.
        update_post_meta($coupon_id, '_activetrail_coupon', 'yes');
        update_post_meta($coupon_id, '_activetrail_created_date', current_time('mysql'));
        
        // Store external_id if provided.
        if (!empty($coupon_data['external_id'])) {
            update_post_meta($coupon_id, '_activetrail_external_id', $coupon_data['external_id']);
        }
        
        // Store account_id if provided.
        if (!empty($coupon_data['account_id'])) {
            update_post_meta($coupon_id, '_activetrail_account_id', $coupon_data['account_id']);
        }
        
        return array(
            'success' => true,
            'message' => 'Coupon created successfully',
            'coupon_id' => $coupon_id,
            'coupon_code' => $coupon_data['coupon_code'],
            'external_id' => $coupon_data['external_id'] ?? null
        );
        
    } catch (Exception $e) {
        return array(
            'success' => false,
            'message' => 'Failed to create coupon: ' . $e->getMessage()
        );
    }
}

/**
 * Update existing WooCommerce coupon
 */
function activetrail_wc_update_coupon($coupon_id, $coupon_data) {
    try {
        $coupon = new WC_Coupon($coupon_id);
        
        // Update basic properties.
        $coupon->set_discount_type($coupon_data['discount_type']);
        $coupon->set_amount(floatval($coupon_data['amount']));
        
        // Update description.
        if (!empty($coupon_data['description'])) {
            $coupon->set_description($coupon_data['description']);
        }
        
        // Update expiry date.
        if (!empty($coupon_data['date_expires'])) {
            $coupon->set_date_expires($coupon_data['date_expires']);
        }
        
        // Update usage limits.
        if (isset($coupon_data['usage_limit'])) {
            $coupon->set_usage_limit($coupon_data['usage_limit']);
        }
        
        if (isset($coupon_data['usage_limit_per_user'])) {
            $coupon->set_usage_limit_per_user($coupon_data['usage_limit_per_user']);
        }
        
        // Update amount limits.
        if (isset($coupon_data['minimum_amount'])) {
            $coupon->set_minimum_amount(floatval($coupon_data['minimum_amount']));
        }
        
        if (isset($coupon_data['maximum_amount'])) {
            $coupon->set_maximum_amount(floatval($coupon_data['maximum_amount']));
        }
        
        // Update boolean properties.
        if (isset($coupon_data['individual_use'])) {
            $coupon->set_individual_use($coupon_data['individual_use']);
        }
        
        if (isset($coupon_data['free_shipping'])) {
            $coupon->set_free_shipping($coupon_data['free_shipping']);
        }
        
        // Update product restrictions.
        if (isset($coupon_data['product_ids'])) {
            $coupon->set_product_ids($coupon_data['product_ids']);
        }
        
        if (isset($coupon_data['excluded_product_ids'])) {
            $coupon->set_excluded_product_ids($coupon_data['excluded_product_ids']);
        }
        
        if (isset($coupon_data['product_categories'])) {
            $coupon->set_product_categories($coupon_data['product_categories']);
        }
        
        if (isset($coupon_data['excluded_product_categories'])) {
            $coupon->set_excluded_product_categories($coupon_data['excluded_product_categories']);
        }
        
        // Update email restrictions.
        if (isset($coupon_data['email_restrictions'])) {
            $coupon->set_email_restrictions($coupon_data['email_restrictions']);
        }
        
        // Save coupon.
        $coupon->save();
        
        // Update metadata.
        update_post_meta($coupon_id, '_activetrail_updated_date', current_time('mysql'));
        
        return array(
            'success' => true,
            'message' => 'Coupon updated successfully',
            'coupon_id' => $coupon_id,
            'coupon_code' => $coupon_data['coupon_code'],
            'external_id' => $coupon_data['external_id'] ?? null
        );
        
    } catch (Exception $e) {
        return array(
            'success' => false,
            'message' => 'Failed to update coupon: ' . $e->getMessage()
        );
    }
}

/**
 * Find coupon by external_id
 */
function activetrail_wc_find_coupon_by_external_id($external_id) {
    global $wpdb;
    
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Direct query needed for coupon lookup
    $coupon_id = $wpdb->get_var($wpdb->prepare(
        "SELECT post_id FROM {$wpdb->postmeta} 
         WHERE meta_key = '_activetrail_external_id' 
         AND meta_value = %s",
        $external_id
    ));
    
    return $coupon_id ? intval($coupon_id) : false;
}

// Hook the coupon creation handler.
add_action('init', 'activetrail_wc_handle_coupon_request');

/**
 * Handle ActiveTrail coupon creation via GET request (alternative method)
 */
function activetrail_wc_handle_coupon_request_get() {
    // Check if this is a GET coupon creation request.
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- External webhook endpoint, authentication handled separately
    if (!isset($_GET['activetrail_coupon']) || sanitize_text_field(wp_unslash($_GET['activetrail_coupon'])) !== 'createCoupon') {
        return;
    }
    
    // Ensure WooCommerce is fully loaded.
    if (!function_exists('wc_get_product')) {
        if (class_exists('WooCommerce')) {
            WC();
        } else {
            wp_die('WooCommerce is not available', 'ActiveTrail Coupon Error', array('response' => 500));
        }
    }
    
    // Initialize logger if available.
    $logger = function_exists('activetrail_logger') ? activetrail_logger() : null;
    
    if ($logger) {
        $logger->product_feed('🚀 ActiveTrail GET coupon creation request received', ActiveTrail_Logger::LEVEL_INFO, array(
            'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])) : 'unknown',
            'ip' => isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : 'unknown',
            'request_uri' => isset($_SERVER['REQUEST_URI']) ? esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'])) : 'unknown'
        ));
    }
    
    // Check if args parameter exists.
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- External feed endpoint, authentication handled separately
    if (!isset($_GET['args'])) {
        if ($logger) {
            $logger->product_feed('❌ Missing args parameter', ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die('Missing args parameter', 'ActiveTrail Coupon Error', array('response' => 400));
    }
    
    // Decode the args parameter.
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- External feed endpoint, args are base64 encoded and decoded
    $args = isset($_GET['args']) ? wp_unslash($_GET['args']) : '';
    $args = json_decode(base64_decode($args), true);
    
    if (!$args) {
        if ($logger) {
            $logger->product_feed('❌ Invalid args parameter - failed to decode', ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die('Invalid args parameter', 'ActiveTrail Coupon Error', array('response' => 400));
    }

    // Sanitize decoded data.
    if (is_array($args)) {
        $args = activetrail_wc_sanitize_array($args);
    }
    $args = activetrail_wc_normalize_coupon_payload($args);
    
    $requires_amount = empty($args['free_shipping']);
    $required_fields = array('coupon_code', 'discount_type');
    foreach ($required_fields as $field) {
        if (empty($args[$field])) {
            if ($logger) {
                $logger->product_feed('❌ Missing required field: ' . $field, ActiveTrail_Logger::LEVEL_ERROR);
            }
            wp_die(esc_html('Missing required field: ' . $field), 'ActiveTrail Coupon Error', array('response' => 400));
        }
    }
    if ($requires_amount && empty($args['amount'])) {
        if ($logger) {
            $logger->product_feed('❌ Missing required field: amount', ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die('Missing required field: amount', 'ActiveTrail Coupon Error', array('response' => 400));
    } elseif (!$requires_amount && !isset($args['amount'])) {
        $args['amount'] = '0';
    }
    
    // Validate discount type.
    $valid_types = array('percent', 'fixed_cart', 'fixed_product');
    if (!in_array($args['discount_type'], $valid_types)) {
        if ($logger) {
            $logger->product_feed('❌ Invalid discount type: ' . $args['discount_type'], ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die(esc_html('Invalid discount_type. Must be one of: ' . implode(', ', $valid_types)), 'ActiveTrail Coupon Error', array('response' => 400));
    }
    
    if ($requires_amount) {
        $amount = floatval($args['amount']);
        if ($amount <= 0) {
            if ($logger) {
                $logger->product_feed('❌ Invalid amount: ' . $args['amount'], ActiveTrail_Logger::LEVEL_ERROR);
            }
            wp_die('Amount must be greater than 0', 'ActiveTrail Coupon Error', array('response' => 400));
        }
        
        if ($args['discount_type'] === 'percent' && $amount > 100) {
            if ($logger) {
                $logger->product_feed('❌ Percent amount cannot exceed 100: ' . $args['amount'], ActiveTrail_Logger::LEVEL_ERROR);
            }
            wp_die('Percent amount cannot exceed 100', 'ActiveTrail Coupon Error', array('response' => 400));
        }
    } else {
        $args['amount'] = '0';
    }
    
    // Check for existing coupon by external_id (idempotency).
    if (!empty($args['external_id'])) {
        $existing_coupon_id = activetrail_wc_find_coupon_by_external_id($args['external_id']);
        if ($existing_coupon_id) {
            // Update existing coupon.
            $result = activetrail_wc_update_coupon($existing_coupon_id, $args);
            if ($result['success']) {
                if ($logger) {
                    $logger->product_feed('✅ Coupon updated successfully via GET: ' . $args['coupon_code'] . ' (ID: ' . $existing_coupon_id . ')', ActiveTrail_Logger::LEVEL_INFO);
                }
                wp_send_json($result, 200);
            } else {
                if ($logger) {
                    $logger->product_feed('❌ Failed to update coupon via GET: ' . $result['message'], ActiveTrail_Logger::LEVEL_ERROR);
                }
                wp_send_json($result, 500);
            }
        }
    }
    
    // Check if coupon code already exists (without external_id).
    if (empty($args['external_id'])) {
        $existing_coupon_id = wc_get_coupon_id_by_code($args['coupon_code']);
        if ($existing_coupon_id) {
            if ($logger) {
                $logger->product_feed('❌ Coupon code already exists without external_id via GET: ' . $args['coupon_code'], ActiveTrail_Logger::LEVEL_ERROR);
            }
            wp_send_json(array(
                'success' => false,
                'message' => 'Coupon code already exists. Use external_id for idempotency.'
            ), 409);
        }
    }
    
    // Create new coupon.
    $result = activetrail_wc_create_coupon($args);
    
    if ($result['success']) {
        if ($logger) {
            $logger->product_feed('✅ Coupon created successfully via GET: ' . $result['coupon_code'] . ' (ID: ' . $result['coupon_id'] . ')', ActiveTrail_Logger::LEVEL_INFO);
        }
        wp_send_json($result, 201);
    } else {
        if ($logger) {
            $logger->product_feed('❌ Failed to create coupon via GET: ' . $result['message'], ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_send_json($result, 500);
    }
}

// Hook the GET coupon creation handler.
add_action('init', 'activetrail_wc_handle_coupon_request_get');

/**
 * Handle ActiveTrail coupon creation with defaults via GET request
 */
function activetrail_wc_handle_coupon_request_defaults() {
    // Check if this is a default coupon creation request.
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- External webhook endpoint, authentication handled separately
    $activetrail_coupon = isset($_GET['activetrail_coupon']) ? sanitize_text_field(wp_unslash($_GET['activetrail_coupon'])) : '';
    if ($activetrail_coupon !== 'createDefault') {
        return;
    }
    
    // Ensure WooCommerce is fully loaded.
    if (!function_exists('wc_get_product')) {
        if (class_exists('WooCommerce')) {
            WC();
        } else {
            wp_die('WooCommerce is not available', 'ActiveTrail Coupon Error', array('response' => 500));
        }
    }
    
    // Initialize logger if available.
    $logger = function_exists('activetrail_logger') ? activetrail_logger() : null;
    
    if ($logger) {
        $logger->product_feed('🚀 ActiveTrail default coupon creation request received', ActiveTrail_Logger::LEVEL_INFO, array(
            'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])) : 'unknown',
            'ip' => isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : 'unknown',
            'request_uri' => isset($_SERVER['REQUEST_URI']) ? esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'])) : 'unknown'
        ));
    }
    
    // Check if args parameter exists.
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- External feed endpoint, authentication handled separately
    if (!isset($_GET['args'])) {
        if ($logger) {
            $logger->product_feed('❌ Missing args parameter for default coupon', ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die('Missing args parameter', 'ActiveTrail Coupon Error', array('response' => 400));
    }
    
    // Decode the args parameter.
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- External feed endpoint, args are base64 encoded and decoded
    $args = isset($_GET['args']) ? wp_unslash($_GET['args']) : '';
    $args = json_decode(base64_decode($args), true);
    
    if (!$args) {
        if ($logger) {
            $logger->product_feed('❌ Invalid args parameter for default coupon - failed to decode', ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die('Invalid args parameter', 'ActiveTrail Coupon Error', array('response' => 400));
    }

    // Sanitize decoded data.
    if (is_array($args)) {
        $args = activetrail_wc_sanitize_array($args);
    }
    $args = activetrail_wc_normalize_coupon_payload($args);
    
    // Validate required fields (only amount is required for default creation).
    if (empty($args['amount'])) {
        if ($logger) {
            $logger->product_feed('❌ Missing required field: amount for default coupon', ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die('Missing required field: amount', 'ActiveTrail Coupon Error', array('response' => 400));
    }
    
    // Validate amount.
    $amount = floatval($args['amount']);
    if ($amount <= 0) {
        if ($logger) {
            $logger->product_feed('❌ Invalid amount for default coupon: ' . $args['amount'], ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die('Amount must be greater than 0', 'ActiveTrail Coupon Error', array('response' => 400));
    }
    
    // Check for existing coupon by external_id (idempotency).
    if (!empty($args['external_id'])) {
        $existing_coupon_id = activetrail_wc_find_coupon_by_external_id($args['external_id']);
        if ($existing_coupon_id) {
            // Update existing coupon.
            $result = activetrail_wc_update_coupon($existing_coupon_id, $args);
            if ($result['success']) {
                if ($logger) {
                    $logger->product_feed('✅ Default coupon updated successfully: ' . $result['coupon_code'] . ' (ID: ' . $existing_coupon_id . ')', ActiveTrail_Logger::LEVEL_INFO);
                }
                wp_send_json($result, 200);
            } else {
                if ($logger) {
                    $logger->product_feed('❌ Failed to update default coupon: ' . $result['message'], ActiveTrail_Logger::LEVEL_ERROR);
                }
                wp_send_json($result, 500);
            }
        }
    }
    
    // Create new coupon with defaults.
    $result = activetrail_wc_create_coupon_with_defaults($args);
    
    if ($result['success']) {
        if ($logger) {
            $logger->product_feed('✅ Default coupon created successfully: ' . $result['coupon_code'] . ' (ID: ' . $result['coupon_id'] . ')', ActiveTrail_Logger::LEVEL_INFO);
        }
        wp_send_json($result, 201);
    } else {
        if ($logger) {
            $logger->product_feed('❌ Failed to create default coupon: ' . $result['message'], ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_send_json($result, 500);
    }
}

// Hook the default coupon creation handler.
add_action('init', 'activetrail_wc_handle_coupon_request_defaults');

/**
 * Handle ActiveTrail coupon creation with custom prefix via GET request
 */
function activetrail_wc_handle_coupon_request_prefix() {
    // Check if this is a prefix coupon creation request.
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- External webhook endpoint, authentication handled separately
    $activetrail_coupon = isset($_GET['activetrail_coupon']) ? sanitize_text_field(wp_unslash($_GET['activetrail_coupon'])) : '';
    if ($activetrail_coupon !== 'createPrefix') {
        return;
    }
    
    // Ensure WooCommerce is fully loaded.
    if (!function_exists('wc_get_product')) {
        if (class_exists('WooCommerce')) {
            WC();
        } else {
            wp_die('WooCommerce is not available', 'ActiveTrail Coupon Error', array('response' => 500));
        }
    }
    
    // Initialize logger if available.
    $logger = function_exists('activetrail_logger') ? activetrail_logger() : null;
    
    if ($logger) {
        $logger->product_feed('🚀 ActiveTrail prefix coupon creation request received', ActiveTrail_Logger::LEVEL_INFO, array(
            'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])) : 'unknown',
            'ip' => isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : 'unknown',
            'request_uri' => isset($_SERVER['REQUEST_URI']) ? esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'])) : 'unknown'
        ));
    }
    
    // Check if args parameter exists.
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- External feed endpoint, authentication handled separately
    if (!isset($_GET['args'])) {
        if ($logger) {
            $logger->product_feed('❌ Missing args parameter for prefix coupon', ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die('Missing args parameter', 'ActiveTrail Coupon Error', array('response' => 400));
    }
    
    // Decode the args parameter.
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- External feed endpoint, args are base64 encoded and decoded
    $args = isset($_GET['args']) ? wp_unslash($_GET['args']) : '';
    $args = json_decode(base64_decode($args), true);
    
    if (!$args) {
        if ($logger) {
            $logger->product_feed('❌ Invalid args parameter for prefix coupon - failed to decode', ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die('Invalid args parameter', 'ActiveTrail Coupon Error', array('response' => 400));
    }

    // Sanitize decoded data.
    if (is_array($args)) {
        $args = activetrail_wc_sanitize_array($args);
    }
    $args = activetrail_wc_normalize_coupon_payload($args);
    
    // Check if prefix is provided.
    if (empty($args['prefix'])) {
        if ($logger) {
            $logger->product_feed('❌ Missing prefix parameter for prefix coupon', ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die('Missing prefix parameter', 'ActiveTrail Coupon Error', array('response' => 400));
    }
    
    // Validate required fields (only amount is required for prefix creation).
    if (empty($args['amount'])) {
        if ($logger) {
            $logger->product_feed('❌ Missing required field: amount for prefix coupon', ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die('Missing required field: amount', 'ActiveTrail Coupon Error', array('response' => 400));
    }
    
    // Validate amount.
    $amount = floatval($args['amount']);
    if ($amount <= 0) {
        if ($logger) {
            $logger->product_feed('❌ Invalid amount for prefix coupon: ' . $args['amount'], ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die('Amount must be greater than 0', 'ActiveTrail Coupon Error', array('response' => 400));
    }
    
    // Check for existing coupon by external_id (idempotency).
    if (!empty($args['external_id'])) {
        $existing_coupon_id = activetrail_wc_find_coupon_by_external_id($args['external_id']);
        if ($existing_coupon_id) {
            // Update existing coupon.
            $result = activetrail_wc_update_coupon($existing_coupon_id, $args);
            if ($result['success']) {
                if ($logger) {
                    $logger->product_feed('✅ Prefix coupon updated successfully: ' . $result['coupon_code'] . ' (ID: ' . $existing_coupon_id . ')', ActiveTrail_Logger::LEVEL_INFO);
                }
                wp_send_json($result, 200);
            } else {
                if ($logger) {
                    $logger->product_feed('❌ Failed to update prefix coupon: ' . $result['message'], ActiveTrail_Logger::LEVEL_ERROR);
                }
                wp_send_json($result, 500);
            }
        }
    }
    
    // Create new coupon with custom prefix.
    $result = activetrail_wc_create_coupon_with_prefix($args['prefix'], $args);
    
    if ($result['success']) {
        if ($logger) {
            $logger->product_feed('✅ Prefix coupon created successfully: ' . $result['coupon_code'] . ' (ID: ' . $result['coupon_id'] . ')', ActiveTrail_Logger::LEVEL_INFO);
        }
        wp_send_json($result, 201);
    } else {
        if ($logger) {
            $logger->product_feed('❌ Failed to create prefix coupon: ' . $result['message'], ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_send_json($result, 500);
    }
}

// Hook the prefix coupon creation handler.
add_action('init', 'activetrail_wc_handle_coupon_request_prefix');

/**
 * Handle ActiveTrail coupon creation with automatic code via GET request
 */
function activetrail_wc_handle_coupon_request_auto() {
    // Check if this is an auto code coupon creation request.
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- External webhook endpoint, authentication handled separately
    $activetrail_coupon = isset($_GET['activetrail_coupon']) ? sanitize_text_field(wp_unslash($_GET['activetrail_coupon'])) : '';
    if ($activetrail_coupon !== 'createAuto') {
        return;
    }
    
    // Ensure WooCommerce is fully loaded.
    if (!function_exists('wc_get_product')) {
        if (class_exists('WooCommerce')) {
            WC();
        } else {
            wp_die('WooCommerce is not available', 'ActiveTrail Coupon Error', array('response' => 500));
        }
    }
    
    // Initialize logger if available.
    $logger = function_exists('activetrail_logger') ? activetrail_logger() : null;
    
    if ($logger) {
        $logger->product_feed('🚀 ActiveTrail auto code coupon creation request received', ActiveTrail_Logger::LEVEL_INFO, array(
            'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])) : 'unknown',
            'ip' => isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : 'unknown',
            'request_uri' => isset($_SERVER['REQUEST_URI']) ? esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'])) : 'unknown'
        ));
    }
    
    // Check if args parameter exists.
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- External feed endpoint, authentication handled separately
    if (!isset($_GET['args'])) {
        if ($logger) {
            $logger->product_feed('❌ Missing args parameter for auto code coupon', ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die('Missing args parameter', 'ActiveTrail Coupon Error', array('response' => 400));
    }
    
    // Decode the args parameter.
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- External feed endpoint, args are base64 encoded and decoded
    $args = isset($_GET['args']) ? wp_unslash($_GET['args']) : '';
    $args = json_decode(base64_decode($args), true);
    
    if (!$args) {
        if ($logger) {
            $logger->product_feed('❌ Invalid args parameter for auto code coupon - failed to decode', ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die('Invalid args parameter', 'ActiveTrail Coupon Error', array('response' => 400));
    }

    // Sanitize decoded data.
    if (is_array($args)) {
        $args = activetrail_wc_sanitize_array($args);
    }
    $args = activetrail_wc_normalize_coupon_payload($args);
    
    // Validate required fields (only amount is required for auto code creation).
    if (empty($args['amount'])) {
        if ($logger) {
            $logger->product_feed('❌ Missing required field: amount for auto code coupon', ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die('Missing required field: amount', 'ActiveTrail Coupon Error', array('response' => 400));
    }
    
    // Validate amount.
    $amount = floatval($args['amount']);
    if ($amount <= 0) {
        if ($logger) {
            $logger->product_feed('❌ Invalid amount for auto code coupon: ' . $args['amount'], ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die('Amount must be greater than 0', 'ActiveTrail Coupon Error', array('response' => 400));
    }
    
    // Check for existing coupon by external_id (idempotency).
    if (!empty($args['external_id'])) {
        $existing_coupon_id = activetrail_wc_find_coupon_by_external_id($args['external_id']);
        if ($existing_coupon_id) {
            // Update existing coupon.
            $result = activetrail_wc_update_coupon($existing_coupon_id, $args);
            if ($result['success']) {
                if ($logger) {
                    $logger->product_feed('✅ Auto code coupon updated successfully: ' . $result['coupon_code'] . ' (ID: ' . $existing_coupon_id . ')', ActiveTrail_Logger::LEVEL_INFO);
                }
                wp_send_json($result, 200);
            } else {
                if ($logger) {
                    $logger->product_feed('❌ Failed to update auto code coupon: ' . $result['message'], ActiveTrail_Logger::LEVEL_ERROR);
                }
                wp_send_json($result, 500);
            }
        }
    }
    
    // Create new coupon with automatic code generation.
    $result = activetrail_wc_create_coupon_auto_code($args);
    
    if ($result['success']) {
        if ($logger) {
            $logger->product_feed('✅ Auto code coupon created successfully: ' . $result['coupon_code'] . ' (ID: ' . $result['coupon_id'] . ')', ActiveTrail_Logger::LEVEL_INFO);
        }
        wp_send_json($result, 201);
    } else {
        if ($logger) {
            $logger->product_feed('❌ Failed to create auto code coupon: ' . $result['message'], ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_send_json($result, 500);
    }
}

// Hook the auto code coupon creation handler.
add_action('init', 'activetrail_wc_handle_coupon_request_auto');

/**
 * Handle ActiveTrail coupon creation with custom defaults via GET request
 */
function activetrail_wc_handle_coupon_request_custom_defaults() {
    // Check if this is a custom defaults coupon creation request.
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- External webhook endpoint, authentication handled separately
    $activetrail_coupon = isset($_GET['activetrail_coupon']) ? sanitize_text_field(wp_unslash($_GET['activetrail_coupon'])) : '';
    if ($activetrail_coupon !== 'createCustom') {
        return;
    }
    
    // Ensure WooCommerce is fully loaded.
    if (!function_exists('wc_get_product')) {
        if (class_exists('WooCommerce')) {
            WC();
        } else {
            wp_die('WooCommerce is not available', 'ActiveTrail Coupon Error', array('response' => 500));
        }
    }
    
    // Initialize logger if available.
    $logger = function_exists('activetrail_logger') ? activetrail_logger() : null;
    
    if ($logger) {
        $logger->product_feed('🚀 ActiveTrail custom defaults coupon creation request received', ActiveTrail_Logger::LEVEL_INFO, array(
            'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])) : 'unknown',
            'ip' => isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : 'unknown',
            'request_uri' => isset($_SERVER['REQUEST_URI']) ? esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'])) : 'unknown'
        ));
    }
    
    // Check if args parameter exists.
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- External feed endpoint, authentication handled separately
    if (!isset($_GET['args'])) {
        if ($logger) {
            $logger->product_feed('❌ Missing args parameter for custom defaults coupon', ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die('Missing args parameter', 'ActiveTrail Coupon Error', array('response' => 400));
    }
    
    // Decode the args parameter.
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- External feed endpoint, args are base64 encoded and decoded
    $args = isset($_GET['args']) ? wp_unslash($_GET['args']) : '';
    $args = json_decode(base64_decode($args), true);
    
    if (!$args) {
        if ($logger) {
            $logger->product_feed('❌ Invalid args parameter for custom defaults coupon - failed to decode', ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die('Invalid args parameter', 'ActiveTrail Coupon Error', array('response' => 400));
    }

    // Sanitize decoded data.
    if (is_array($args)) {
        $args = activetrail_wc_sanitize_array($args);
    }
    $args = activetrail_wc_normalize_coupon_payload($args);
    
    // Check if custom_defaults parameter exists.
    if (!isset($args['custom_defaults'])) {
        if ($logger) {
            $logger->product_feed('❌ Missing custom_defaults parameter for custom defaults coupon', ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die('Missing custom_defaults parameter', 'ActiveTrail Coupon Error', array('response' => 400));
    }
    
    // Validate required fields (only amount is required for custom defaults creation).
    if (empty($args['amount'])) {
        if ($logger) {
            $logger->product_feed('❌ Missing required field: amount for custom defaults coupon', ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die('Missing required field: amount', 'ActiveTrail Coupon Error', array('response' => 400));
    }
    
    // Validate amount.
    $amount = floatval($args['amount']);
    if ($amount <= 0) {
        if ($logger) {
            $logger->product_feed('❌ Invalid amount for custom defaults coupon: ' . $args['amount'], ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_die('Amount must be greater than 0', 'ActiveTrail Coupon Error', array('response' => 400));
    }
    
    // Check for existing coupon by external_id (idempotency).
    if (!empty($args['external_id'])) {
        $existing_coupon_id = activetrail_wc_find_coupon_by_external_id($args['external_id']);
        if ($existing_coupon_id) {
            // Update existing coupon.
            $result = activetrail_wc_update_coupon($existing_coupon_id, $args);
            if ($result['success']) {
                if ($logger) {
                    $logger->product_feed('✅ Custom defaults coupon updated successfully: ' . $result['coupon_code'] . ' (ID: ' . $existing_coupon_id . ')', ActiveTrail_Logger::LEVEL_INFO);
                }
                wp_send_json($result, 200);
            } else {
                if ($logger) {
                    $logger->product_feed('❌ Failed to update custom defaults coupon: ' . $result['message'], ActiveTrail_Logger::LEVEL_ERROR);
                }
                wp_send_json($result, 500);
            }
        }
    }
    
    // Extract custom defaults.
    $custom_defaults = $args['custom_defaults'];
    unset($args['custom_defaults']); // Remove from main data
    
    // Create new coupon with custom defaults.
    $result = activetrail_wc_create_coupon_custom_defaults($args, $custom_defaults);
    
    if ($result['success']) {
        if ($logger) {
            $logger->product_feed('✅ Custom defaults coupon created successfully: ' . $result['coupon_code'] . ' (ID: ' . $result['coupon_id'] . ')', ActiveTrail_Logger::LEVEL_INFO);
        }
        wp_send_json($result, 201);
    } else {
        if ($logger) {
            $logger->product_feed('❌ Failed to create custom defaults coupon: ' . $result['message'], ActiveTrail_Logger::LEVEL_ERROR);
        }
        wp_send_json($result, 500);
    }
}

// Hook the custom defaults coupon creation handler.
add_action('init', 'activetrail_wc_handle_coupon_request_custom_defaults');

/**
 * Generate unique coupon code
 *
 * @param string $prefix Prefix for the coupon code
 * @return string Unique coupon code
 */
function activetrail_wc_generate_unique_code($prefix = 'AT') {
    $code = $prefix . wp_generate_password(6, false);
    
    // Check if code already exists.
    if (!empty(wc_get_coupon_id_by_code($code))) {
        return activetrail_wc_generate_unique_code($prefix); // Recursive call until unique code found
    }
    
    return $code;
}

/**
 * Create coupon with default values
 *
 * @param array $data Coupon data
 * @return array Result
 */
function activetrail_wc_create_coupon_with_defaults($data) {
    // Set default values.
    $defaults = array(
        'discount_type' => 'fixed_cart',
        'amount' => 0,
        'usage_limit' => 1,
        'usage_limit_per_user' => 1,
        'expiry_date' => gmdate('Y-m-d', strtotime('+371 days')),
        'free_shipping' => false,
        'product_ids' => null,
        'individual_use' => false,
        'exclude_product_ids' => '',
        'minimum_amount' => '',
        'maximum_amount' => '',
        'product_categories' => '',
        'exclude_product_categories' => '',
        'exclude_sale_items' => true,
        'description' => ''
    );
    
    // Merge with provided data.
    $merged = array_merge($defaults, $data);
    
    // Generate unique code if not provided.
    if (empty($merged['coupon_code'])) {
        $prefix = $merged['prefix'] ?? 'AT';
        $merged['coupon_code'] = activetrail_wc_generate_unique_code($prefix);
    }
    
    // Create the coupon.
    return activetrail_wc_create_coupon($merged);
}

/**
 * Create coupon with custom prefix
 *
 * @param string $prefix Custom prefix for coupon code
 * @param array $data Coupon data
 * @return array Result
 */
function activetrail_wc_create_coupon_with_prefix($prefix, $data) {
    // Set the prefix.
    $data['prefix'] = $prefix;
    
    // Create coupon with defaults.
    return activetrail_wc_create_coupon_with_defaults($data);
}

/**
 * Create coupon with automatic unique code
 *
 * @param array $data Coupon data
 * @return array Result
 */
function activetrail_wc_create_coupon_auto_code($data) {
    // Generate unique code automatically.
    $prefix = $data['prefix'] ?? 'AT';
    $data['coupon_code'] = activetrail_wc_generate_unique_code($prefix);
    
    // Create the coupon.
    return activetrail_wc_create_coupon($data);
}

/**
 * Create coupon with custom defaults
 *
 * @param array $data Coupon data
 * @param array $custom_defaults Custom default values
 * @return array Result
 */
function activetrail_wc_create_coupon_custom_defaults($data, $custom_defaults = array()) {
    // Set custom default values.
    $defaults = array(
        'discount_type' => 'fixed_cart',
        'amount' => 0,
        'usage_limit' => 1,
        'usage_limit_per_user' => 1,
        'expiry_date' => gmdate('Y-m-d', strtotime('+371 days')),
        'free_shipping' => false,
        'product_ids' => null,
        'individual_use' => false,
        'exclude_product_ids' => '',
        'minimum_amount' => '',
        'maximum_amount' => '',
        'product_categories' => '',
        'exclude_product_categories' => '',
        'exclude_sale_items' => true,
        'description' => ''
    );
    
    // Merge with custom defaults.
    $defaults = array_merge($defaults, $custom_defaults);
    
    // Merge with provided data.
    $merged = array_merge($defaults, $data);
    
    // Generate unique code if not provided.
    if (empty($merged['coupon_code'])) {
        $prefix = $merged['prefix'] ?? 'AT';
        $merged['coupon_code'] = activetrail_wc_generate_unique_code($prefix);
    }
    
    // Create the coupon.
    return activetrail_wc_create_coupon($merged);
}

/**
 * Handle product feed export requests
 */
function activetrail_wc_handle_export_request() {
    // Check if this is an export request.
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- External feed endpoint, authentication handled separately
    if (!isset($_GET['activetrail_export']) || !isset($_GET['key'])) {
        return;
    }
    
    // Ensure WooCommerce is fully loaded.
    if (!function_exists('wc_get_product')) {
        // Force load WooCommerce if not loaded.
        if (class_exists('WooCommerce')) {
            WC();
        } else {
            wp_die('WooCommerce is not available', 'ActiveTrail Export Error', array('response' => 500));
        }
    }
    
    // Initialize logger if available.
    $logger = function_exists('activetrail_logger') ? activetrail_logger() : null;
    
    if ($logger) {
        $logger->product_feed('🔧 WooCommerce initialization check', ActiveTrail_Logger::LEVEL_DEBUG, array(
            'wc_get_product_exists' => function_exists('wc_get_product'),
            'woocommerce_class_exists' => class_exists('WooCommerce'),
            'wc_function_exists' => function_exists('WC')
        ));
    }
    
    if ($logger) {
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- External feed endpoint, authentication handled separately
        $logger->product_feed('🚀 Product feed export request received', ActiveTrail_Logger::LEVEL_INFO, array(
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- External feed endpoint, authentication handled separately
            'export_type' => isset($_GET['activetrail_export']) ? sanitize_text_field(wp_unslash($_GET['activetrail_export'])) : 'unknown',
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- External feed endpoint, authentication handled separately
            'key_provided' => !empty($_GET['key']),
            'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])) : 'unknown',
            'ip' => isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : 'unknown',
            'request_uri' => isset($_SERVER['REQUEST_URI']) ? esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'])) : 'unknown'
        ));
    }
    
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- External feed endpoint, authentication handled separately
    $export_type = isset($_GET['activetrail_export']) ? sanitize_text_field(wp_unslash($_GET['activetrail_export'])) : '';
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- External feed endpoint, authentication handled separately
    $provided_key = isset($_GET['key']) ? sanitize_text_field(wp_unslash($_GET['key'])) : '';
    
    if ($logger) {
        $logger->product_feed('📋 Request parameters validated', ActiveTrail_Logger::LEVEL_DEBUG, array(
            'export_type' => $export_type,
            'key_length' => strlen($provided_key)
        ));
    }
    
    // Validate export type.
    if (!in_array($export_type, array('google', 'facebook'))) {
        if ($logger) {
            $logger->product_feed('❌ Invalid export type provided', ActiveTrail_Logger::LEVEL_ERROR, array(
                'provided_type' => $export_type,
                'allowed_types' => array('google', 'facebook')
            ));
        }
        wp_die('Invalid export type', 'ActiveTrail Export Error', array('response' => 400));
    }
    
    // Get the stored key for this export type.
    $stored_key = get_option('activetrail_' . $export_type . '_feed_key', '');
    
    if ($logger) {
        $logger->product_feed('🔑 Checking stored key', ActiveTrail_Logger::LEVEL_DEBUG, array(
            'export_type' => $export_type,
            'stored_key_exists' => !empty($stored_key),
            'stored_key_length' => strlen($stored_key),
            'keys_match' => ($provided_key === $stored_key)
        ));
    }
    
    // Validate the key.
    if (empty($stored_key) || $provided_key !== $stored_key) {
        if ($logger) {
            $logger->product_feed('❌ Key validation failed', ActiveTrail_Logger::LEVEL_ERROR, array(
                'stored_key_empty' => empty($stored_key),
                'keys_match' => ($provided_key === $stored_key),
                'export_type' => $export_type
            ));
        }
        wp_die('Invalid or expired key', 'ActiveTrail Export Error', array('response' => 403));
    }
    
    // Check if product feed is enabled.
    $settings = get_option('activetrail_wc_settings', array());
    $enable_product_feed = true; // Always enabled
    
    if ($logger) {
        $logger->product_feed('⚙️ Checking product feed settings', ActiveTrail_Logger::LEVEL_DEBUG, array(
            'enable_product_feed' => $enable_product_feed,
            'settings_exist' => !empty($settings),
            'settings_keys' => array_keys($settings)
        ));
    }
    
    if (!$enable_product_feed) {
        if ($logger) {
            $logger->product_feed('❌ Product feed is disabled in settings', ActiveTrail_Logger::LEVEL_WARNING);
        }
        wp_die('Product feed is disabled', 'ActiveTrail Export Error', array('response' => 403));
    }
    
    // Load the product feed template.
    $template_file = ACTIVETRAIL_WC_PLUGIN_DIR . 'templates/product-feed.php';
    
    if ($logger) {
        $logger->product_feed('📁 Checking template file', ActiveTrail_Logger::LEVEL_DEBUG, array(
            'template_path' => $template_file,
            'file_exists' => file_exists($template_file),
            'file_readable' => is_readable($template_file)
        ));
    }
    
    if (!file_exists($template_file)) {
        if ($logger) {
            $logger->product_feed('❌ Template file not found', ActiveTrail_Logger::LEVEL_ERROR, array(
                'expected_path' => $template_file
            ));
        }
        wp_die('Feed template not found', 'ActiveTrail Export Error', array('response' => 500));
    }
    
    if ($logger) {
        $logger->product_feed('✅ All validations passed, generating feed', ActiveTrail_Logger::LEVEL_INFO, array(
            'export_type' => $export_type
        ));
    }
    
    // Check for format parameter (allows XML with Facebook or JSON with Google).
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- External feed endpoint, authentication handled separately
    $format = isset($_GET['format']) ? sanitize_text_field(wp_unslash($_GET['format'])) : '';
    
    // Determine feed format based on format parameter or default behavior.
    if ($format === 'xml') {
        $feed_format = 'xml';
    } elseif ($format === 'json') {
        $feed_format = 'json';
    } else {
        // Default behavior: both google and facebook = XML.
        $feed_format = 'xml';
    }
    
    // Set appropriate headers based on feed format.
    if ($feed_format === 'xml') {
        header('Content-Type: application/xml; charset=utf-8');
        $filename = ($export_type === 'google') ? 'google-products.xml' : 'facebook-products.xml';
        header('Content-Disposition: inline; filename="' . $filename . '"');
        if ($logger) {
            $logger->product_feed('📄 Set XML headers', ActiveTrail_Logger::LEVEL_DEBUG, array(
                'export_type' => $export_type,
                'format' => $format
            ));
        }
    } else {
        header('Content-Type: application/json; charset=utf-8');
        $filename = ($export_type === 'facebook') ? 'facebook-products.json' : 'google-products.json';
        header('Content-Disposition: inline; filename="' . $filename . '"');
        if ($logger) {
            $logger->product_feed('📄 Set JSON headers', ActiveTrail_Logger::LEVEL_DEBUG, array(
                'export_type' => $export_type,
                'format' => $format
            ));
        }
    }
    
    // Prevent caching.
    header('Cache-Control: no-cache, must-revalidate');
    header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
    
    // Update last export time.
    update_option('activetrail_feed_last_update', current_time('mysql'));
    
    if ($logger) {
        $logger->product_feed('🕒 Updated last export time', ActiveTrail_Logger::LEVEL_DEBUG, array(
            'timestamp' => current_time('mysql')
        ));
    }
    
    // Include the template and pass the export type and format.
    $GLOBALS['activetrail_export_type'] = $export_type;
    $GLOBALS['activetrail_feed_format'] = $feed_format;
    
    if ($logger) {
        $logger->product_feed('🎯 Including template file to generate feed', ActiveTrail_Logger::LEVEL_INFO, array(
            'template_file' => $template_file,
            'export_type' => $export_type
        ));
    }
    
    // Include template to generate feed content.
    // Template stores content in $GLOBALS['activetrail_feed_output'] instead of echoing.
    // Use output buffering to catch any accidental output.
    ob_start();
    include $template_file;
    $ob_content = ob_get_clean();
    
    // Get the generated content from global variable (preferred method).
    $feed_content = isset( $GLOBALS['activetrail_feed_output'] ) ? $GLOBALS['activetrail_feed_output'] : '';
    
    // If global variable is empty but output buffer has content, use that (fallback).
    if ( empty( $feed_content ) && ! empty( $ob_content ) ) {
        $feed_content = $ob_content;
    }
    
    if ($logger) {
        $logger->product_feed('✅ Feed generation completed successfully', ActiveTrail_Logger::LEVEL_INFO, array(
            'export_type' => $export_type,
            'content_length' => strlen($feed_content),
            'content_preview' => substr($feed_content, 0, 500) . '...',
            'content_empty' => empty($feed_content),
            'starts_with_xml' => strpos($feed_content, '<?xml') === 0,
            'has_rss_tag' => strpos($feed_content, '<rss') !== false,
            'from_global' => isset($GLOBALS['activetrail_feed_output']),
            'from_buffer' => !empty($ob_content),
            'first_100_chars' => substr($feed_content, 0, 100)
        ));
    }
    
    // Also log to logger for immediate debugging.
    if (function_exists('activetrail_logger')) {
        $logger = activetrail_logger();
        $logger->product_feed('Feed generated with length: ' . strlen($feed_content), 'DEBUG');
        $logger->product_feed('Content preview: ' . substr($feed_content, 0, 200), 'DEBUG');
    }
    
    // Output the feed content.
    // Check if there was an error (stored in global variable).
    $is_error = isset( $GLOBALS['activetrail_feed_error'] ) && $GLOBALS['activetrail_feed_error'];
    
    if ( empty( $feed_content ) ) {
        // No content generated - output error.
        if ( $feed_format === 'json' ) {
            status_header( 500 );
            wp_send_json_error( array( 'error' => 'Feed generation failed - no content generated' ) );
        } else {
            header( 'Content-Type: application/xml; charset=utf-8' );
            status_header( 500 );
            echo '<?xml version="1.0" encoding="UTF-8"?><error>Feed generation failed - no content generated</error>';
            wp_die();
        }
    }
    
    // For JSON feeds: output JSON string directly with proper headers (feed is pre-encoded with specific flags).
    // For XML feeds: output XML directly with proper headers and exit.
    if ( $feed_format === 'json' ) {
        // JSON feed is pre-encoded by generate_facebook_json() with JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE.
        // Output directly to preserve formatting and encoding flags.
        if ( $is_error ) {
            status_header( 500 );
        }
        header( 'Content-Type: application/json; charset=utf-8' );
        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- JSON feed content is generated server-side using wp_json_encode() and must be output as-is for external feed parsers. Escaping would break JSON structure.
        echo $feed_content;
        // Use exit instead of wp_die() for JSON feeds - wp_die() outputs HTML which breaks JSON structure.
        exit;
    } else {
        // XML feed - output directly with proper headers.
        // Headers are already set above, but ensure Content-Type is correct.
        if ( $is_error ) {
            status_header( 500 );
        }
        header( 'Content-Type: application/xml; charset=utf-8' );
        
        // Ensure feed content starts with XML declaration (safety check).
        if ( ! empty( $feed_content ) && strpos( $feed_content, '<?xml' ) !== 0 ) {
            // Content doesn't start with XML declaration - this shouldn't happen, but log it.
            if ( $logger ) {
                $logger->product_feed( '⚠️ WARNING: Feed content does not start with XML declaration', ActiveTrail_Logger::LEVEL_WARNING, array(
                    'first_100_chars' => substr( $feed_content, 0, 100 ),
                    'content_length' => strlen( $feed_content )
                ) );
            }
            // If content doesn't start with XML, something is wrong - don't output it.
            wp_die( 'Error: Feed content is invalid', 'Feed Error', array( 'response' => 500 ) );
        }
        
        // Clear any output that might have been sent before.
        if ( ob_get_level() > 0 ) {
            ob_clean();
        }
        
        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- XML feed content is generated server-side and must be output as-is for external feed parsers. Escaping would break XML structure.
        echo $feed_content;
        // Use exit instead of wp_die() for XML feeds - wp_die() outputs HTML which breaks XML structure.
        exit;
    }
}

// Hook after WooCommerce registers its post types and taxonomies (priority 5) so wc_get_product() works correctly.
add_action('init', 'activetrail_wc_handle_export_request', 10);

/**
 * Alternative hook for export requests - even earlier
 */
function activetrail_wc_handle_export_request_early() {
    // Check if this is an export request.
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- External feed endpoint, authentication handled separately
    if (!isset($_GET['activetrail_export']) || !isset($_GET['key'])) {
        return;
    }
    
    // Force load WooCommerce early.
    if (!function_exists('wc_get_product')) {
        // Try to load WooCommerce.
        if (file_exists(WP_PLUGIN_DIR . '/woocommerce/woocommerce.php')) {
            include_once WP_PLUGIN_DIR . '/woocommerce/woocommerce.php';
        }
        
        // Initialize WooCommerce if class exists.
        if (class_exists('WooCommerce') && !function_exists('wc_get_product')) {
            // Force initialize WooCommerce.
            // Note: $woocommerce is a core WooCommerce global variable, not our plugin's variable.
            if (!isset($GLOBALS['woocommerce']) || !$GLOBALS['woocommerce']) {
                // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Core WooCommerce global variable
                $GLOBALS['woocommerce'] = new WooCommerce();
            }
            WC();
        }
    }
}

// Hook even earlier to ensure WooCommerce is loaded.
add_action('plugins_loaded', 'activetrail_wc_handle_export_request_early', 5);

/**
 * Add custom cron schedules
 * 
 * Register cron schedules early, before any event scheduling
 */
function activetrail_wc_add_cron_schedules($schedules) {
    $schedules['every_minute'] = array(
        'interval' => 60, // 1 minute in seconds
        // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch -- Text domain 'activetrail-for-woocommerce' is correct per WordPress review requirements
        'display' => esc_html__('Every Minute', 'activetrail-for-woocommerce')
    );
    
    $schedules['every_five_minutes'] = array(
        'interval' => 300, // 5 minutes in seconds
        // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch -- Text domain 'activetrail-for-woocommerce' is correct per WordPress review requirements
        'display' => esc_html__('Every 5 Minutes', 'activetrail-for-woocommerce')
    );
    
    $schedules['every_fifteen_minutes'] = array(
        'interval' => 900, // 15 minutes in seconds
        // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch -- Text domain 'activetrail-for-woocommerce' is correct per WordPress review requirements
        'display' => esc_html__('Every 15 Minutes', 'activetrail-for-woocommerce')
    );
    
    return $schedules;
}
// Use priority 5 to ensure schedules are registered before any events are scheduled.
add_filter('cron_schedules', 'activetrail_wc_add_cron_schedules', 5);

/**
 * Plugin activation hook
 */
function activetrail_wc_activate() {
    // Check if WooCommerce is active.
    if (!activetrail_wc_check_woocommerce()) {
        deactivate_plugins(plugin_basename(__FILE__));
        wp_die(
            // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch -- Text domain 'activetrail-for-woocommerce' is correct per WordPress review requirements
            esc_html__('ActiveTrail for WooCommerce requires WooCommerce to be installed and active.', 'activetrail-for-woocommerce'),
            // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch -- Text domain 'activetrail-for-woocommerce' is correct per WordPress review requirements
            esc_html__('Plugin Activation Error', 'activetrail-for-woocommerce'),
            array('back_link' => true)
        );
    }

    // Set default options.
    $default_options = array(
        'api_key'                   => '',
        'group_id'                  => '',
        'order_statuses'            => array( 'completed' ),
        'enable_checkout_consent'   => true,
        'consent_text'              => 'I agree to receive marketing emails', // Will be translated when displayed
        'consent_checked_by_default' => false,
        'consent_required'          => false,
        'enable_registration_consent' => false,
        'sync_without_consent'      => false,
    );

    add_option( 'activetrail_wc_settings', $default_options );
    
    // Create or update custom database tables and store DB schema version.
    activetrail_wc_create_tables();
    update_option( 'activetrail_wc_db_version', ACTIVETRAIL_WC_VERSION );

    // Flush rewrite rules so /activetrail-feed.xml resolves immediately after activation.
    add_rewrite_rule( '^activetrail-feed\.xml$', 'index.php?activetrail_feed=xml', 'top' );
    add_rewrite_rule( '^activetrail-feed\.json$', 'index.php?activetrail_feed=json', 'top' );
    flush_rewrite_rules();
}

/**
 * Ensure database tables are up to date on plugin load.
 *
 * This runs on existing installations as well (not רק בהפעלה ראשונה),
 * ומפעיל שוב את dbDelta אם גרסת הסכמה השתנתה – כך מתווספות עמודות חדשות
 * כמו sync_attempts, בלי לאבד נתונים, בכל סביבה שבה מתקינים או מעדכנים את התוסף.
 */
function activetrail_wc_maybe_update_tables() {
    $installed_version = get_option( 'activetrail_wc_db_version' );

    if ( $installed_version === ACTIVETRAIL_WC_VERSION ) {
        return;
    }

    // (Re)create/upgrade tables – dbDelta יוסיף רק מה שחסר.
    activetrail_wc_create_tables();

    update_option( 'activetrail_wc_db_version', ACTIVETRAIL_WC_VERSION );
}
// Run after plugins_loaded so של־$wpdb יש את כל המידע, אבל לפני שאנחנו מתחילים להשתמש בטבלאות.
add_action( 'plugins_loaded', 'activetrail_wc_maybe_update_tables', 20 );

/**
 * One-time clear of old 2-arg debounced cart sync cron events.
 * New code schedules events with 3 args (session_id, snapshot_time, cart_data) so sync works without session.
 * Run once per site so old scheduled events are removed and only 3-arg events run.
 */
function activetrail_wc_clear_legacy_debounced_cron() {
    if ( get_option( 'activetrail_wc_debounced_cron_v2', '' ) === 'yes' ) {
        return;
    }
    wp_clear_scheduled_hook( 'activetrail_debounced_cart_sync' );
    update_option( 'activetrail_wc_debounced_cron_v2', 'yes' );
}
add_action( 'plugins_loaded', 'activetrail_wc_clear_legacy_debounced_cron', 21 );

/**
 * Schedule plugin cron events
 * 
 * This function is called after cron schedules are registered
 * to ensure all events use valid schedules
 */
function activetrail_wc_schedule_events() {
    // Schedule abandoned cart sync if not already scheduled.
    if (!wp_next_scheduled('activetrail_sync_abandoned_carts')) {
        wp_schedule_event(time(), 'every_minute', 'activetrail_sync_abandoned_carts');
    }
    
    // Schedule event queue processing if not already scheduled.
    if (!wp_next_scheduled('activetrail_process_event_queue')) {
        wp_schedule_event(time(), 'every_five_minutes', 'activetrail_process_event_queue');
    }
    
    // Schedule expired coupons cleanup if not already scheduled.
    if (!wp_next_scheduled('activetrail_clean_expired_coupons')) {
        wp_schedule_event(time(), 'daily', 'activetrail_clean_expired_coupons');
    }
}
// Schedule events after cron schedules are registered.
add_action('init', 'activetrail_wc_schedule_events', 20);

/**
 * Send disconnect API call to ActiveTrail
 * Helper function for deactivation and uninstall hooks
 */
function activetrail_wc_send_disconnect() {
    // Get API key from settings.
    require_once ACTIVETRAIL_WC_PLUGIN_DIR . 'includes/settings/class-settings.php';
    $settings = ActiveTrail_Settings::get_all();
    $api_key = isset( $settings['api_key'] ) ? $settings['api_key'] : '';

    if ( empty( $api_key ) ) {
        // No API key, nothing to disconnect.
        if ( function_exists( 'activetrail_logger' ) ) {
            // Log explicitly so שנוכל לראות בלוג למה לא נשלח disconnect.
            activetrail_logger()->info( 'Skip store disconnect: no API key configured', 'SETTINGS' );
        }
        return;
    }

    // Load API client.
    require_once ACTIVETRAIL_WC_PLUGIN_DIR . 'includes/api/class-activetrail-api-client.php';
    $api_client = new ActiveTrail_API_Client( $api_key );

    // Log לפני הקריאה בפועל כדי שנדע ש‑deactivate/uninstall ניסה לשלוח disconnect.
    if ( function_exists( 'activetrail_logger' ) ) {
        activetrail_logger()->info( 'Attempting store disconnect on plugin deactivation/uninstall', 'SETTINGS' );
    }

    // Send disconnect call with short timeout (fail silently if it fails).
    $result = $api_client->disconnect_store();

    // Log תוצאת הקריאה (בלי לחשוף פרטים רגישים).
    if ( function_exists( 'activetrail_logger' ) ) {
        $success_flag = ( is_array( $result ) && isset( $result['success'] ) )
            ? ( $result['success'] ? 'success' : 'failure' )
            : 'unknown';

        $extra_message = ( is_array( $result ) && ! empty( $result['message'] ) )
            ? ' | message: ' . $result['message']
            : '';

        activetrail_logger()->info(
            'Store disconnect finished with status: ' . $success_flag . $extra_message,
            'SETTINGS'
        );
    }

    // Result is logged internally, we don't need to do anything else here.
    // Failures are handled silently to avoid blocking admin UX.
}

/**
 * Plugin deactivation hook
 */
function activetrail_wc_deactivate() {
    global $wpdb;

    // Send disconnect API call.
    activetrail_wc_send_disconnect();

    // Clear all scheduled events.
    wp_clear_scheduled_hook('activetrail_sync_abandoned_carts');
    wp_clear_scheduled_hook('activetrail_process_event_queue');
    wp_clear_scheduled_hook('activetrail_clean_expired_coupons');
    wp_clear_scheduled_hook('activetrail_debounced_cart_sync');

    // Delete all plugin options.
    $options = array(
        'activetrail_wc_settings',
        'activetrail_api_key',
        'activetrail_group_id',
        'activetrail_store_status',
        'activetrail_language',
        'activetrail_order_statuses',
        'activetrail_enable_checkout_consent',
        'activetrail_consent_text',
        'activetrail_consent_checked_by_default',
        'activetrail_consent_required',
        'activetrail_sync_without_consent',
        'activetrail_enable_cart_tracking',
        'activetrail_enable_product_feed',
        'activetrail_feed_title',
        'activetrail_feed_description',
        'activetrail_debug_mode',
        'activetrail_historical_sync_status',
        'activetrail_status_mapping',
    );
    foreach ( $options as $option ) {
        delete_option( $option );
    }

    // Delete any remaining options with the activetrail prefix.
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
    $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE 'activetrail_%'" );

    // Remove transients.
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
    $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_activetrail_%'" );
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
    $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_timeout_activetrail_%'" );
}

/**
 * Create custom database tables
 */
function activetrail_wc_create_tables() {
    global $wpdb;

    $charset_collate = $wpdb->get_charset_collate();

    // Cart tracking table (enhanced).
    $cart_table = $wpdb->prefix . 'activetrail_cart_tracking';
    $cart_sql = "CREATE TABLE $cart_table (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        session_id varchar(255) NOT NULL,
        user_id bigint(20) DEFAULT NULL,
        cart_data longtext NOT NULL,
        email varchar(100) DEFAULT NULL,
        created_at datetime DEFAULT CURRENT_TIMESTAMP,
        updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        synced tinyint(1) DEFAULT 0,
        sync_attempts int(11) DEFAULT 0,
        last_sync_attempt datetime DEFAULT NULL,
        abandonment_sent tinyint(1) DEFAULT 0,
        recovery_email_sent tinyint(1) DEFAULT 0,
        PRIMARY KEY (id),
        KEY session_id (session_id),
        KEY user_id (user_id),
        KEY email (email),
        KEY synced (synced),
        KEY sync_attempts (sync_attempts),
        KEY abandonment_sent (abandonment_sent)
    ) $charset_collate;";

    // Events tracking table.
    $events_table = $wpdb->prefix . 'activetrail_events';
    $events_sql = "CREATE TABLE $events_table (
        id bigint(20) NOT NULL AUTO_INCREMENT,
        event_type varchar(50) NOT NULL,
        customer_email varchar(100) DEFAULT NULL,
        customer_id bigint(20) DEFAULT NULL,
        session_id varchar(255) DEFAULT NULL,
        product_id bigint(20) DEFAULT NULL,
        order_id bigint(20) DEFAULT NULL,
        event_data longtext DEFAULT NULL,
        event_value decimal(10,2) DEFAULT NULL,
        currency varchar(3) DEFAULT NULL,
        created_at datetime DEFAULT CURRENT_TIMESTAMP,
        synced tinyint(1) DEFAULT 0,
        sync_attempts int(11) DEFAULT 0,
        last_sync_attempt datetime DEFAULT NULL,
        PRIMARY KEY (id),
        KEY event_type (event_type),
        KEY customer_email (customer_email),
        KEY customer_id (customer_id),
        KEY product_id (product_id),
        KEY synced (synced),
        KEY created_at (created_at)
    ) $charset_collate;";

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

// Register activation and deactivation hooks.
register_activation_hook(__FILE__, 'activetrail_wc_activate');
register_deactivation_hook(__FILE__, 'activetrail_wc_deactivate');


/**
 * Add plugin action links
 */
function activetrail_wc_plugin_action_links($links) {
    // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch -- Text domain 'activetrail-for-woocommerce' is correct per WordPress review requirements
    $settings_link = '<a href="' . admin_url('admin.php?page=wc-settings&tab=activetrail') . '">' . esc_html__('Settings', 'activetrail-for-woocommerce') . '</a>';
    array_unshift($links, $settings_link);
    return $links;
}
add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'activetrail_wc_plugin_action_links');
