<?php
if (!defined('ABSPATH')) exit;
/**
 * Ensure payment table exists before any Stripe operations
 */
function sitsel_ensure_payment_table_exists() {
    global $wpdb;
    $table = $wpdb->prefix . "sitsel_payments";
    
    // Check cache first
    $cache_key = 'sitsel_payments_table_exists';
    $exists = wp_cache_get($cache_key);
    
    if (false === $exists) {
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $exists = $wpdb->get_var($wpdb->prepare(
            "SELECT 1 FROM information_schema.TABLES WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s",
            DB_NAME,
            $table
        ));
        
        // Cache for 24 hours
        wp_cache_set($cache_key, $exists ? 1 : 0, '', 86400);
    }
    
    return (bool) $exists;
}
/**
 * AJAX Stripe Handler
 */
add_action('wp_ajax_sitsel_create_checkout', 'sitsel_create_checkout');
add_action('wp_ajax_nopriv_sitsel_create_checkout', 'sitsel_create_checkout');

function sitsel_get_stripe_settings(){
    $opts = get_option('sits_elementor_addons_options', []);
    return [
        'secret_key'   => $opts['stripe_secret_key']        ?? '',
        'publishable'  => $opts['stripe_publishable_key']   ?? '',
        'currency'     => strtoupper($opts['stripe_currency'] ?? 'USD'),
        'success_url'  => $opts['stripe_success_url']       ?? home_url('/?payment=success'),
        'cancel_url'   => $opts['stripe_cancel_url']        ?? home_url('/?payment=cancel'),
        'webhook_key'  => $opts['stripe_webhook_secret']    ?? '',
    ];
}

function sitsel_find_stripe_price($data, $page_id, $depth = 0){
    // Security: Prevent infinite recursion
    $max_depth = 10;
    if ($depth > $max_depth || !is_array($data)) {
        return 0;
    }
    
    foreach ($data as $item) {
        if (isset($item['widgetType']) && $item['widgetType'] === 'sitsel_stripe_checkout') {
            $settings = $item['settings'] ?? [];

            // Check price source
            if (isset($settings['price_source']) && $settings['price_source'] === 'acf') {
                $acf_field = $settings['acf_price_field'] ?? '';
                if ($acf_field && function_exists('get_field')) {
                    $price = floatval(get_field($acf_field, $page_id));
                    if ($price > 0) {
                        return $price;
                    }
                }
            } else if (isset($settings['product_price'])) {
                return floatval($settings['product_price']);
            }
        }
        
        // Recurse into nested elements with depth tracking
        if (isset($item['elements']) && is_array($item['elements'])) {
            $result = sitsel_find_stripe_price($item['elements'], $page_id, $depth + 1);
            if ($result) return $result;
        }
    }
    
    return 0;
}

function sitsel_create_checkout(){
    
    if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'sitsel_checkout_nonce')) {
        
        wp_send_json_error('Security check failed.');
        return;
    }

  
    $ip = isset($_SERVER['REMOTE_ADDR'])
    ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR']))
    : '0.0.0.0';
    $rate_limit_key = 'sitsel_checkout_attempt_' . md5($ip);
    $attempts = intval(get_transient($rate_limit_key));
    
    if ($attempts >= 5) {
        wp_send_json_error('Too many payment attempts. Please try again in 1 hour.');
        return;
    }
    
    // Increment attempts counter
    set_transient($rate_limit_key, $attempts + 1, 3600);
    

    if (!sitsel_ensure_payment_table_exists()) {
        wp_send_json_error('Payment system not properly initialized. Please contact administrator.');
        return;
    }
    
    global $wpdb;
    $table = $wpdb->prefix . "sitsel_payments";

    $stripe = sitsel_get_stripe_settings();
    if (!$stripe['secret_key']) {
        wp_send_json_error("Stripe Secret Key not configured.");
        return;
    }

    // ✅ Sanitize and validate inputs
    $name  = isset($_POST['name']) ? sanitize_text_field(wp_unslash($_POST['name'])) : '';
    $email = isset($_POST['email']) ? sanitize_email(wp_unslash($_POST['email'])) : '';
    $page_id = isset($_POST['page']) ? intval(wp_unslash($_POST['page'])) : 0;
    $widget_currency = isset($_POST['currency']) ? sanitize_text_field(wp_unslash($_POST['currency'])) : '';
    $frontend_price = isset($_POST['price']) ? floatval(wp_unslash($_POST['price'])) : 0;
    $button_id = isset($_POST['button_id']) ? sanitize_text_field(wp_unslash($_POST['button_id'])) : '';

    // ✅ Log the request for debugging
    

    if (!$name || !$email || !$page_id) {
        wp_send_json_error('Missing required fields.');
        return;
    }
    
    $page = get_post($page_id);
    $page_title = $page ? $page->post_title : 'Unknown Page';
    $page_data = json_encode(['id' => $page_id, 'title' => $page_title]);
    
    // Determine final currency
    $final_currency = !empty($widget_currency) ? strtoupper($widget_currency) : $stripe['currency'];

    // Define zero-decimal currencies
    $zero_decimal_currencies = ['JPY', 'KRW', 'VND', 'CLP'];
    $is_zero_decimal = in_array($final_currency, $zero_decimal_currencies, true);

    $actual_price = $frontend_price;

    // Minimum prices
    $currency_minimums = [
        'USD' => 0.50,
        'EUR' => 0.55,
        'GBP' => 0.46,
        'INR' => 48.00,
        'AUD' => 0.86,
        'CAD' => 0.78,
        'JPY' => 86,
        'CNY' => 4.15,
        'CHF' => 0.52,
        'AED' => 2.13,
    ];
    $minimum_price = $currency_minimums[$final_currency] ?? 0.50;

   // Validate price
if ($actual_price < $minimum_price) {
    // Determine currency symbol (PHP 7.4 compatible)
    $currency_symbol = '';
    switch ($final_currency) {
        case 'INR':
            $currency_symbol = '₹';
            break;
        case 'USD':
            $currency_symbol = '$';
            break;
        case 'EUR':
            $currency_symbol = '€';
            break;
        case 'GBP':
            $currency_symbol = '£';
            break;
        default:
            $currency_symbol = strtoupper($final_currency) . ' ';
            break;
    }

    $formatted_minimum = number_format($minimum_price, $is_zero_decimal ? 0 : 2);
    $error_message = sprintf("Price must be at least %s%s.", $currency_symbol, $formatted_minimum);
    
    wp_send_json_error($error_message);
    return;
}

    // Calculate Stripe amount
    $stripe_amount = $is_zero_decimal ? intval($actual_price) : intval(round($actual_price * 100, 0, PHP_ROUND_HALF_UP));
    $price_to_store = $actual_price;

    

    // ✅ Insert into database
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    $inserted = $wpdb->insert($table, [
        'name' => $name,
        'email' => $email,
        'price' => floatval($price_to_store),
        'currency' => $final_currency,
        'page_data' => $page_data,
        'button_id' => $button_id,
        'provider' => 'stripe',
        'status' => 'pending'
    ], ['%s', '%s', '%f', '%s', '%s', '%s', '%s', '%s']);
    
    if ($inserted === false) {
        
        wp_send_json_error('Database error occurred.');
        return;
    }
    
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
    $record_id = $wpdb->insert_id;
    
    
    
    // Build success/cancel URLs
    $success_url = $stripe['success_url'];
    $separator = strpos($success_url, '?') === false ? '?' : '&';
    $success_url .= $separator . 'session_id={CHECKOUT_SESSION_ID}';

    $cancel_url = $stripe['cancel_url'];
    $separator_cancel = strpos($cancel_url, '?') === false ? '?' : '&';
    $cancel_url .= $separator_cancel . 'session_id={CHECKOUT_SESSION_ID}';

    // ✅ Create Stripe checkout session
    $response = wp_remote_post('https://api.stripe.com/v1/checkout/sessions', [
        'timeout' => 20,  // Wait up to 20 seconds
        'headers' => [
            'Authorization' => 'Bearer ' . $stripe['secret_key'],
        ],
        'body' => [
            'success_url' => $success_url,
            'cancel_url'  => $cancel_url,
            'mode' => 'payment',
            'customer_email' => $email,
            'metadata[record_id]' => $record_id,
            'line_items[0][price_data][currency]' => $final_currency,
            'line_items[0][price_data][product_data][name]' => $name . ' Payment',
            'line_items[0][price_data][unit_amount]' => $stripe_amount,
            'line_items[0][quantity]' => 1
        ]
    ]);

    if (is_wp_error($response)) {
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->update(
            $table,
            ['status' => 'failed'],
            ['id' => $record_id],
            ['%s'],
            ['%d']
        );
        
        wp_send_json_error($response->get_error_message());
        return;
    }

    $body = json_decode(wp_remote_retrieve_body($response), true);

    if (!empty($body['id']) && !empty($body['url'])) {
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->update(
            $table,
            [
                'payment_id' => $body['id'],
                'status' => 'pending'
            ],
            ['id' => $record_id],
            ['%s', '%s'],
            ['%d']
        );

        
        wp_send_json_success(['url' => $body['url']]);
    } else {
        $error_msg = isset($body['error']['message']) ? $body['error']['message'] : 'Unknown Stripe error';
        // ✅ FIXED: Use prepared statement for update
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->update(
            $table,
            ['status' => 'failed'],
            ['id' => $record_id],
            ['%s'],
            ['%d']
        );
        
        wp_send_json_error('Stripe error: ' . $error_msg);
    }
}
/**
 * Verify Stripe webhook signature without SDK
 * Based on Stripe's webhook signature specification
 */
function sitsel_verify_stripe_signature($payload, $sig_header, $secret) {
    if (empty($sig_header)) {
        return false;
    }

    // Parse signature header
    $sig_parts = explode(',', $sig_header);
    $timestamp = null;
    $signatures = [];

    foreach ($sig_parts as $part) {
        $item = explode('=', trim($part), 2);
        if (count($item) === 2) {
            if ($item[0] === 't') {
                $timestamp = $item[1];
            } elseif ($item[0] === 'v1') {
                $signatures[] = $item[1];
            }
        }
    }

    if ($timestamp === null || empty($signatures)) {
        return false;
    }

    // Check timestamp tolerance (5 minutes)
    $current_time = time();
    if (abs($current_time - intval($timestamp)) > 300) {
        return false;
    }

    // Compute expected signature
    $signed_payload = $timestamp . '.' . $payload;
    $expected_sig = hash_hmac('sha256', $signed_payload, $secret);

    // Compare signatures using timing-safe comparison
    foreach ($signatures as $signature) {
        if (hash_equals($expected_sig, $signature)) {
            return true;
        }
    }

    return false;
}
/**
 * Register REST API endpoint for Stripe Webhook
 */
add_action('rest_api_init', function () {
    register_rest_route('sitsel/v1', '/stripe-webhook', [
        'methods' => 'POST',
        'callback' => 'sitsel_stripe_webhook',
        'permission_callback' => '__return_true'
    ]);
});

function sitsel_stripe_webhook($request){
     
    if (!sitsel_ensure_payment_table_exists()) {
        return new WP_REST_Response(['error' => 'Payment system not initialized'], 500);
    }
    global $wpdb;
    $table = $wpdb->prefix . "sitsel_payments";

    $stripe = sitsel_get_stripe_settings();
    $endpoint_secret = $stripe['webhook_key'];

    if (!$endpoint_secret) {
        return new WP_REST_Response(['error' => 'Webhook secret missing'], 400);
    }

    $payload = $request->get_body();
    $sig_header = $request->get_header('stripe-signature');

    // ✅ VERIFY SIGNATURE MANUALLY (without Stripe SDK)
    if (!sitsel_verify_stripe_signature($payload, $sig_header, $endpoint_secret)) {
        return new WP_REST_Response(['error' => 'Invalid signature'], 403);
    }

    $event = json_decode($payload, true);

    if (!$event || empty($event['type'])) {
        return new WP_REST_Response(['error' => 'Invalid payload'], 400);
    }

    if ($event['type'] === 'checkout.session.completed') {
        $session = $event['data']['object'];
        $session_id = $session['id'];
        $record_id = isset($session['metadata']['record_id']) ? intval($session['metadata']['record_id']) : null;

         if ($record_id) {
            // ✅ FIXED: Use prepared statement with proper format strings
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $wpdb->update(
                $table,
                [
                    'status' => 'success',
                    'payment_id' => $session_id
                ],
                ['id' => $record_id],
                ['%s', '%s'],
                ['%d']
            );
        } 
    }

    return new WP_REST_Response(['received' => true], 200);
}