<?php
/**
 * Stripe Webhook Handler
 * Handles payment confirmation events from Stripe
 */

// Add simple GET test for webhook accessibility
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
    http_response_code(200);
    echo json_encode([
        'status' => 'Webhook endpoint is accessible',
        'timestamp' => date('Y-m-d H:i:s'),
        'method' => 'GET'
    ]);
    exit;
}

require_once 'stripe_config.php';
require_once 'db_config.php';

try {
    require_once 'vendor/autoload.php'; // If using Composer
} catch (Exception $e) {
    // Fallback: include Stripe library manually
    die('Stripe PHP library not found.');
}

use Stripe\Stripe;
use Stripe\Webhook;
use Stripe\Exception\SignatureVerificationException;

// Set Stripe API key
Stripe::setApiKey(StripeConfig::getSecretKey());

// Force reload configuration to get latest webhook secret from database
require_once 'config_manager.php';
ConfigManager::forceReload();

// Get webhook endpoint secret from environment configuration
$endpoint_secret = StripeConfig::getWebhookSecret();

// Webhook secret loaded successfully

$payload = @file_get_contents('php://input');
$sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE'] ?? '';

// Log webhook request for security monitoring
$request_ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
$user_agent = $_SERVER['HTTP_USER_AGENT'] ?? 'unknown';
error_log('Stripe Webhook: Received request - Method: ' . $_SERVER['REQUEST_METHOD'] . ' from IP: ' . $request_ip);
error_log('Stripe Webhook: Payload length: ' . strlen($payload) . ', User-Agent: ' . substr($user_agent, 0, 100));
error_log('Stripe Webhook: Has signature: ' . (!empty($sig_header) ? 'Yes' : 'No'));

$event = null;

try {
    // Verify webhook signature - REQUIRED for security
    if (empty($endpoint_secret)) {
        error_log('SECURITY ERROR: Stripe webhook secret not configured');
        http_response_code(500);
        exit('Webhook configuration error');
    }
    
    if (empty($sig_header)) {
        error_log('SECURITY ERROR: Missing Stripe signature header');
        http_response_code(400);
        exit('Missing signature');
    }
    
    // Construct and verify the event with signature validation
    $event = Webhook::constructEvent($payload, $sig_header, $endpoint_secret);
    error_log('Stripe Webhook: Signature verified successfully for event: ' . $event->type);
    
} catch (UnexpectedValueException $e) {
    // Invalid payload
    error_log('Stripe Webhook: Invalid payload - ' . $e->getMessage());
    http_response_code(400);
    exit('Invalid payload');
} catch (SignatureVerificationException $e) {
    // Invalid signature - potential security attack
    error_log('SECURITY ALERT: Stripe webhook signature verification failed - ' . $e->getMessage());
    error_log('SECURITY ALERT: Potential unauthorized webhook attempt from IP: ' . ($_SERVER['REMOTE_ADDR'] ?? 'unknown'));
    http_response_code(401);
    exit('Unauthorized');
} catch (Exception $e) {
    // Other errors
    error_log('Stripe Webhook: Unexpected error - ' . $e->getMessage());
    http_response_code(500);
    exit('Server error');
}

// Database connection
try {
    $pdo = new PDO(
        "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME,
        DB_USER,
        DB_PASS,
        [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
    );
} catch (PDOException $e) {
    error_log('Database connection failed: ' . $e->getMessage());
    http_response_code(500);
    exit();
}

// Handle the event
switch ($event->type) {
    case 'payment_intent.succeeded':
        $paymentIntent = $event->data->object;
        handlePaymentSuccess($pdo, $paymentIntent);
        break;
        
    case 'payment_intent.payment_failed':
        $paymentIntent = $event->data->object;
        handlePaymentFailure($pdo, $paymentIntent);
        break;
        
    case 'payment_intent.canceled':
        $paymentIntent = $event->data->object;
        handlePaymentCanceled($pdo, $paymentIntent);
        break;
        
    default:
        error_log('Stripe Webhook: Unhandled event type ' . $event->type);
}

http_response_code(200);

/**
 * Handle successful payment
 */
function handlePaymentSuccess($pdo, $paymentIntent) {
    try {
        error_log('Stripe Webhook: Processing payment_intent.succeeded for: ' . $paymentIntent->id);
        error_log('Stripe Webhook: Payment amount: $' . ($paymentIntent->amount / 100));
        error_log('Stripe Webhook: Payment metadata: ' . json_encode($paymentIntent->metadata));
        
        // First try to get registration number from payment intent metadata
        $registrationNumber = $paymentIntent->metadata->registration_number ?? null;
        
        // If not found in metadata, look up by payment intent ID or email
        if (!$registrationNumber) {
            error_log('Stripe Webhook: No registration number in payment intent metadata, looking up in database');
            
            // Try to find by payment intent ID first
            $stmt = $pdo->prepare("
                SELECT registration_number, gateway_transaction_id, amount, created_at
                FROM payment_transactions 
                WHERE gateway_transaction_id = ?
            ");
            $stmt->execute([$paymentIntent->id]);
            $transaction = $stmt->fetch(PDO::FETCH_ASSOC);
            
            error_log('Stripe Webhook: Direct payment intent lookup result: ' . json_encode($transaction));
            
            // If not found by payment intent ID, try to find by amount and recent timestamp
            if (!$transaction) {
                error_log('Stripe Webhook: Payment intent not found, trying to match by amount and timestamp');
                
                $amount = $paymentIntent->amount / 100; // Convert cents to dollars
                $paymentTime = date('Y-m-d H:i:s', $paymentIntent->created);
                
                // First, let's see what pending transactions we have
                $debugStmt = $pdo->prepare("
                    SELECT registration_number, gateway_transaction_id, amount, created_at, transaction_status
                    FROM payment_transactions 
                    WHERE transaction_status = 'pending'
                    AND created_at >= DATE_SUB(NOW(), INTERVAL 2 HOUR)
                    ORDER BY created_at DESC
                ");
                $debugStmt->execute();
                $allPending = $debugStmt->fetchAll(PDO::FETCH_ASSOC);
                error_log('Stripe Webhook: Recent pending transactions: ' . json_encode($allPending));
                
                // Look for pending transactions with matching amount within last hour
                $stmt = $pdo->prepare("
                    SELECT registration_number, gateway_transaction_id, amount, created_at
                    FROM payment_transactions 
                    WHERE ABS(amount - ?) < 0.01 
                    AND transaction_status = 'pending'
                    AND created_at >= DATE_SUB(NOW(), INTERVAL 1 HOUR)
                    ORDER BY created_at DESC 
                    LIMIT 1
                ");
                $stmt->execute([$amount]);
                $transaction = $stmt->fetch(PDO::FETCH_ASSOC);
                
                if ($transaction) {
                    error_log("Stripe Webhook: Found registration by amount matching: " . json_encode($transaction));
                } else {
                    error_log("Stripe Webhook: No transaction found with amount $amount in last hour");
                }
            }
            
            if ($transaction) {
                $registrationNumber = $transaction['registration_number'];
                error_log("Stripe Webhook: Found registration number: $registrationNumber");
                
                // Update the transaction record with the payment intent ID for future reference
                $updateStmt = $pdo->prepare("
                    UPDATE payment_transactions 
                    SET gateway_transaction_id = ?
                    WHERE registration_number = ? AND transaction_status = 'pending'
                ");
                $updateStmt->execute([$paymentIntent->id, $registrationNumber]);
                
            } else {
                error_log('Stripe Webhook: No registration found for payment intent: ' . $paymentIntent->id);
                error_log('Stripe Webhook: Payment amount was: $' . ($paymentIntent->amount / 100));
                return;
            }
        }
        
        // Update payment transaction status
        $updateStmt = $pdo->prepare("
            UPDATE payment_transactions 
            SET transaction_status = 'completed',
                transaction_reference = ?,
                gateway_response = ?,
                updated_at = NOW()
            WHERE registration_number = ? AND transaction_status = 'pending'
        ");
        
        $transactionReference = $paymentIntent->charges->data[0]->balance_transaction ?? $paymentIntent->id;
        $gatewayResponse = json_encode([
            'stripe_payment_intent_id' => $paymentIntent->id,
            'amount_received' => $paymentIntent->amount_received,
            'currency' => $paymentIntent->currency,
            'payment_method' => $paymentIntent->charges->data[0]->payment_method_details->type ?? 'card',
            'webhook_processed_at' => date('Y-m-d H:i:s')
        ]);
        
        $updateResult = $updateStmt->execute([
            $transactionReference,
            $gatewayResponse,
            $registrationNumber
        ]);
        
        $rowsUpdated = $updateStmt->rowCount();
        error_log("Stripe Webhook: Payment transaction update - Rows affected: $rowsUpdated");
        
        if ($rowsUpdated > 0) {
            // Update registration status
            $regStmt = $pdo->prepare("
                UPDATE registrations 
                SET payment_status = 'paid',
                    updated_at = NOW()
                WHERE registration_number = ?
            ");
            
            $regResult = $regStmt->execute([$registrationNumber]);
            $regRowsUpdated = $regStmt->rowCount();
            error_log("Stripe Webhook: Registration update - Rows affected: $regRowsUpdated");
            
            if ($regRowsUpdated > 0) {
                error_log("Stripe Webhook: Successfully updated registration $registrationNumber to paid status");
                
                // Send webhook notification for payment status change
                try {
                    require_once 'webhook_service.php';
                    $webhookService = new WebhookService($pdo);
                    
                    // Get registration ID for comprehensive data
                    $regIdStmt = $pdo->prepare("SELECT id FROM registrations WHERE registration_number = ?");
                    $regIdStmt->execute([$registrationNumber]);
                    $regId = $regIdStmt->fetchColumn();
                    
                    // Get full registration data
                    $fullRegistrationData = $webhookService->getFullRegistrationData($regId);
                    
                    $webhookData = [
                        'event_type' => 'payment_status_changed',
                        'trigger' => 'stripe_gateway',
                        'payment_status' => 'paid',
                        'previous_payment_status' => 'pending',
                        'gateway_info' => [
                            'provider' => 'stripe',
                            'transaction_id' => $paymentIntent->id,
                            'amount_paid' => $paymentIntent->amount / 100,
                            'currency' => $paymentIntent->currency,
                            'payment_method' => $paymentIntent->charges->data[0]->payment_method_details->type ?? 'card'
                        ],
                        'updated_at' => date('c')
                    ];
                    
                    // Merge with full registration data
                    if ($fullRegistrationData) {
                        $webhookData = array_merge($webhookData, $fullRegistrationData);
                    }
                    
                    $webhookService->sendWebhook('payment_status_changed', $webhookData);
                    error_log("Stripe webhook: Sent comprehensive payment status webhook for registration $registrationNumber");
                } catch (Exception $e) {
                    error_log('Webhook notification failed: ' . $e->getMessage());
                }
                
                // Auto-confirm stock status for all products in this registration
                $stockStmt = $pdo->prepare("
                    UPDATE registration_products 
                    SET stock_status = 'confirmed', 
                        confirmed_at = NOW(),
                        updated_at = NOW()
                    WHERE registration_id = (
                        SELECT id FROM registrations WHERE registration_number = ?
                    ) AND stock_status = 'reserved'
                ");
                $stockResult = $stockStmt->execute([$registrationNumber]);
                $stockRowsUpdated = $stockStmt->rowCount();
                error_log("Stripe Webhook: Auto-confirmed $stockRowsUpdated product stock items for registration $registrationNumber");
                
                // Update product stock counts
                if ($stockRowsUpdated > 0) {
                    $productStmt = $pdo->prepare("
                        SELECT DISTINCT rp.product_id 
                        FROM registration_products rp
                        JOIN registrations r ON rp.registration_id = r.id
                        WHERE r.registration_number = ?
                    ");
                    $productStmt->execute([$registrationNumber]);
                    $productIds = $productStmt->fetchAll(PDO::FETCH_COLUMN);
                    
                    foreach ($productIds as $productId) {
                        $updateStockStmt = $pdo->prepare("
                            UPDATE products SET 
                                sold_stock = (
                                    SELECT COALESCE(SUM(quantity), 0) 
                                    FROM registration_products 
                                    WHERE product_id = ? AND stock_status = 'confirmed'
                                ),
                                reserved_stock = (
                                    SELECT COALESCE(SUM(quantity), 0) 
                                    FROM registration_products 
                                    WHERE product_id = ? AND stock_status = 'reserved'
                                ),
                                available_stock = GREATEST(0, total_stock - (
                                    SELECT COALESCE(SUM(quantity), 0) 
                                    FROM registration_products 
                                    WHERE product_id = ? AND stock_status IN ('confirmed', 'reserved')
                                ))
                            WHERE id = ?
                        ");
                        $updateStockStmt->execute([$productId, $productId, $productId, $productId]);
                    }
                    error_log("Stripe Webhook: Updated stock counts for " . count($productIds) . " products");
                }
            } else {
                error_log("Stripe Webhook: Failed to update registration status for $registrationNumber");
            }
        } else {
            error_log("Stripe Webhook: Failed to update payment transaction for $registrationNumber");
        }
        
        // Send confirmation email (optional)
        sendPaymentConfirmationEmail($registrationNumber, $paymentIntent);
        
        error_log("Payment confirmed for registration: $registrationNumber");
        
    } catch (Exception $e) {
        error_log('Error handling payment success: ' . $e->getMessage());
    }
}

/**
 * Handle failed payment
 */
function handlePaymentFailure($pdo, $paymentIntent) {
    try {
        // First try to get registration number from payment intent metadata
        $registrationNumber = $paymentIntent->metadata->registration_number ?? null;
        
        // If not found in metadata, look up by payment intent ID in database
        if (!$registrationNumber) {
            $stmt = $pdo->prepare("
                SELECT registration_number 
                FROM payment_transactions 
                WHERE gateway_transaction_id = ?
            ");
            $stmt->execute([$paymentIntent->id]);
            $transaction = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if ($transaction) {
                $registrationNumber = $transaction['registration_number'];
            } else {
                error_log('Stripe Webhook: No registration found for failed payment: ' . $paymentIntent->id);
                return;
            }
        }
        
        // Update payment transaction status
        $stmt = $pdo->prepare("
            UPDATE payment_transactions 
            SET transaction_status = 'failed',
                gateway_response = ?,
                updated_at = NOW()
            WHERE gateway_transaction_id = ?
        ");
        
        $stmt->execute([
            json_encode([
                'stripe_payment_intent_id' => $paymentIntent->id,
                'failure_reason' => $paymentIntent->last_payment_error->message ?? 'Payment failed',
                'failure_code' => $paymentIntent->last_payment_error->code ?? 'unknown'
            ]),
            $paymentIntent->id
        ]);
        
        error_log("Payment failed for registration: $registrationNumber");
        
    } catch (Exception $e) {
        error_log('Error handling payment failure: ' . $e->getMessage());
    }
}

/**
 * Handle canceled payment
 */
function handlePaymentCanceled($pdo, $paymentIntent) {
    try {
        // First try to get registration number from payment intent metadata
        $registrationNumber = $paymentIntent->metadata->registration_number ?? null;
        
        // If not found in metadata, look up by payment intent ID in database
        if (!$registrationNumber) {
            $stmt = $pdo->prepare("
                SELECT registration_number 
                FROM payment_transactions 
                WHERE gateway_transaction_id = ?
            ");
            $stmt->execute([$paymentIntent->id]);
            $transaction = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if ($transaction) {
                $registrationNumber = $transaction['registration_number'];
            } else {
                error_log('Stripe Webhook: No registration found for canceled payment: ' . $paymentIntent->id);
                return;
            }
        }
        
        // Update payment transaction status
        $stmt = $pdo->prepare("
            UPDATE payment_transactions 
            SET transaction_status = 'cancelled',
                updated_at = NOW()
            WHERE gateway_transaction_id = ?
        ");
        
        $stmt->execute([$paymentIntent->id]);
        
        error_log("Payment canceled for registration: $registrationNumber");
        
    } catch (Exception $e) {
        error_log('Error handling payment cancellation: ' . $e->getMessage());
    }
}

/**
 * Send payment confirmation email
 */
function sendPaymentConfirmationEmail($registrationNumber, $paymentIntent) {
    try {
        require_once 'email_notifications.php';
        
        // Send registration confirmation email
        $success = sendRegistrationConfirmationEmailByNumber($registrationNumber);
        
        if ($success) {
            error_log("Registration confirmation email sent for: $registrationNumber");
            
            // Send admin notification for payment received
            sendAdminNotificationByNumber('payment_received', $registrationNumber, 
                'Payment ID: ' . $paymentIntent->id . ', Amount: $' . ($paymentIntent->amount / 100));
        } else {
            error_log("Failed to send registration confirmation email for: $registrationNumber");
        }
        
    } catch (Exception $e) {
        error_log("Error sending payment confirmation email for $registrationNumber: " . $e->getMessage());
    }
}
?>
