<?php
/**
 * Payment Callback V3.2 - OPTIMIZED WITH BETTER ERROR HANDLING
 * File: payment-callback.php (ROOT)
 */

require_once 'app/Core/init.php';
require_once 'app/Core/WalletProcessor.php';

error_reporting(E_ALL);
ini_set('display_errors', 0);
ini_set('log_errors', 1);

if (!Auth::check() || Auth::userType() !== 'customer') {
    redirect('auth/login.php');
}

$reference = $_GET['reference'] ?? '';
$gatewayName = $_GET['gateway'] ?? '';

if (!$reference || !$gatewayName || !isset($_SESSION['pending_booking'])) {
    redirect('items.php?error=invalid_request');
}

$booking = $_SESSION['pending_booking'];
$booking['payment_gateway'] = $gatewayName;

try {
    $db = Database::getInstance();
    $customerModel = new Customer();
    $customer = $customerModel->findByUserId(Auth::id());
    
    if (!$customer) {
        error_log("Payment callback: Customer not found for user " . Auth::id());
        redirect('items.php?error=customer_not_found');
    }
    
    // Check existing payment
    $existingPayment = $db->fetch("
        SELECT id, status, order_id FROM online_payments 
        WHERE transaction_reference = ?
    ", [$reference]);
    
    if ($existingPayment && $existingPayment['status'] === 'successful' && $existingPayment['order_id']) {
        $order = $db->fetch("SELECT order_number FROM orders WHERE id = ?", [$existingPayment['order_id']]);
        
        if ($order) {
            unset($_SESSION['pending_booking']);
            
            // Set flag to send emails in background
            $_SESSION['send_order_emails'] = [
                'order_id' => $existingPayment['order_id'],
                'timestamp' => time()
            ];
            
            redirect("booking-confirmation.php?order={$order['order_number']}");
        }
    }
    
    // Verify payment
    $gatewayFactory = PaymentGatewayFactory::getInstance();
    $gateway = $gatewayFactory->getGateway($gatewayName);
    $verification = $gateway->verify($reference);
    
    if (!$verification['success']) {
        error_log("Payment verification failed for reference: {$reference}");
        redirect('items.php?error=payment_failed');
    }
    
    // Verify amount
    if (abs(floatval($verification['amount']) - floatval($booking['total_amount'])) > 0.01) {
        error_log("Amount mismatch: Expected {$booking['total_amount']}, Got {$verification['amount']}");
        redirect('items.php?error=amount_mismatch');
    }
    
    // ============================================
    // GET CATEGORY COMMISSION - OPTIMIZED QUERY
    // ============================================
    $categoryCommission = $db->fetch("
        SELECT c.commission_percentage 
        FROM items i 
        INNER JOIN categories c ON i.category_id = c.id 
        WHERE i.id = ? 
        LIMIT 1
    ", [$booking['item_id']]);
    
    // Use category commission or default to 10%
    $commissionPercentage = 10.00; // Default
    if ($categoryCommission && isset($categoryCommission['commission_percentage'])) {
        $commissionPercentage = floatval($categoryCommission['commission_percentage']);
    }
    
    // Calculate platform commission (on subtotal only, not security deposit)
    $platformCommission = round(($booking['subtotal'] * $commissionPercentage) / 100, 2);
    
    // Store commission details in booking for WalletProcessor
    $booking['commission_percentage'] = $commissionPercentage;
    $booking['platform_commission'] = $platformCommission;
    
    error_log("Commission calculation: {$commissionPercentage}% on ₦{$booking['subtotal']} = ₦{$platformCommission}");
    
    $db->beginTransaction();
    
    try {
        // Create order WITH COMMISSION
        $orderNumber = 'R' . date('ymdHis') . strtoupper(substr(uniqid(), -3));
        
        $db->execute("
            INSERT INTO orders (
                order_number, customer_id, vendor_id, item_id, 
                start_date, end_date, rental_days, quantity,
                subtotal, security_deposit, platform_fee, total_amount, 
                status, payment_status, rental_completed, security_deposit_status,
                created_at, updated_at
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'confirmed', 'paid', 0, 'held', NOW(), NOW())
        ", [
            $orderNumber, $booking['customer_id'], $booking['vendor_id'], $booking['item_id'],
            $booking['start_date'], $booking['end_date'], $booking['number_of_days'], $booking['quantity'],
            $booking['subtotal'], $booking['security_deposit'], $platformCommission, $booking['total_amount']
        ]);
        
        $orderId = $db->lastInsertId();
        
        if (!$orderId) {
            throw new Exception("Failed to create order");
        }
        
        error_log("Order created: ID={$orderId}, Number={$orderNumber}");
        
        // Create/Update payment record
        if ($existingPayment) {
            $db->execute("
                UPDATE online_payments 
                SET order_id = ?, status = 'successful', 
                    gateway_response = ?, gateway_reference = ?, 
                    completed_at = NOW(), updated_at = NOW() 
                WHERE transaction_reference = ?
            ", [$orderId, json_encode($verification), $verification['reference'] ?? $reference, $reference]);
            $paymentId = $existingPayment['id'];
            error_log("Payment updated: ID={$paymentId}");
        } else {
            $db->execute("
                INSERT INTO online_payments (
                    customer_id, order_id, transaction_reference, payment_gateway, 
                    amount, payment_type, currency, customer_email, status, 
                    gateway_response, gateway_reference, completed_at, created_at, updated_at
                ) VALUES (?, ?, ?, ?, ?, 'order_payment', 'NGN', ?, 'successful', ?, ?, NOW(), NOW(), NOW())
            ", [
                $customer['id'], $orderId, $reference, $gatewayName, 
                $booking['total_amount'], Auth::user()['email'], 
                json_encode($verification), $verification['reference'] ?? $reference
            ]);
            $paymentId = $db->lastInsertId();
            error_log("Payment created: ID={$paymentId}");
        }
        
        // Create commission record
        try {
            $db->execute("
                INSERT INTO commissions (
                    order_id, vendor_id, commission_percentage, 
                    commission_amount, rental_amount, status, created_at
                ) VALUES (?, ?, ?, ?, ?, 'pending', NOW())
            ", [
                $orderId, $booking['vendor_id'], 
                $commissionPercentage, $platformCommission, $booking['subtotal']
            ]);
            error_log("Commission record created");
        } catch (Exception $e) {
            // Commissions table might not exist - log but don't fail
            error_log("Commission record creation skipped: " . $e->getMessage());
        }
        
        // Process wallet
        error_log("Starting wallet processing...");
        $walletProcessor = new WalletProcessor();
        if (!$walletProcessor->processPayment($orderId, $paymentId, $booking)) {
            throw new Exception("Wallet processing failed");
        }
        error_log("Wallet processing completed");
        
        $db->commit();
        error_log("Transaction committed successfully");
        
        unset($_SESSION['pending_booking']);
        
        // Set flag to send emails in background
        $_SESSION['send_order_emails'] = [
            'order_id' => $orderId,
            'timestamp' => time()
        ];
        
        // FAST REDIRECT
        redirect("booking-confirmation.php?order={$orderNumber}");
        
    } catch (Exception $e) {
        $db->rollback();
        error_log("Transaction rolled back: " . $e->getMessage());
        error_log("Stack trace: " . $e->getTraceAsString());
        throw $e;
    }
    
} catch (Exception $e) {
    error_log("Payment callback error: " . $e->getMessage());
    error_log("Reference: {$reference}, Gateway: {$gatewayName}");
    redirect("items.php?error=processing_failed&msg=" . urlencode($e->getMessage()));
}