<?php
/**
 * Wallet Processor V3.0 - SIMPLIFIED SYSTEM
 * File: app/Core/WalletProcessor.php
 * 
 * Handles 4-table wallet system:
 * 1. online_payments
 * 2. order_payment_breakdown (3 records per payment)
 * 3. wallet_transactions (immutable ledger)
 * 4. wallets (fast balance lookup)
 */

class WalletProcessor {
    private $db;
    
    public function __construct() {
        $this->db = Database::getInstance();
    }
    
    /**
     * Process payment - called from payment-callback.php
     * Creates 3 records in order_payment_breakdown (status = onhold)
     * Creates 1 record in wallet_transactions (security held)
     * Updates wallets (security_onhold for customer)
     */
    public function processPayment($order_id, $payment_id, $booking) {
        try {
            $this->db->beginTransaction();
            
            $rental_amount = floatval($booking['subtotal']);
            $security_deposit = floatval($booking['security_deposit']);
            $total_amount = floatval($booking['total_amount']);
            
            $commission_rate = 10.00;
            $platform_commission = $rental_amount * ($commission_rate / 100);
            $vendor_earning = $rental_amount - $platform_commission;
            
            // Get IDs
            $order = $this->db->fetch("
                SELECT c.id as customer_id, c.user_id as customer_user_id, 
                       v.user_id as vendor_user_id
                FROM orders o
                JOIN customers c ON o.customer_id = c.id
                JOIN vendors v ON o.vendor_id = v.id
                WHERE o.id = ?
            ", [$order_id]);
            
            $admin = $this->db->fetch("SELECT id FROM users WHERE user_type = 'admin' ORDER BY id ASC LIMIT 1");
            $admin_user_id = $admin['id'] ?? 1;
            
            $source = $booking['payment_gateway'] ?? 'paystack';
            
            // ========================================
            // CREATE 3 RECORDS IN order_payment_breakdown
            // ========================================
            
            // Record 1: Customer security deposit
            $this->db->execute("
                INSERT INTO order_payment_breakdown 
                (order_id, payment_id, customer_id, user_id, type, amount, total_amount, status, source)
                VALUES (?, ?, ?, ?, 'security_deposit', ?, ?, 'onhold', ?)
            ", [$order_id, $payment_id, $order['customer_id'], $order['customer_user_id'], 
                $security_deposit, $total_amount, $source]);
            
            $security_breakdown_id = $this->db->lastInsertId();
            
            // Record 2: Vendor rental
            $this->db->execute("
                INSERT INTO order_payment_breakdown 
                (order_id, payment_id, customer_id, user_id, type, amount, total_amount, status, source)
                VALUES (?, ?, ?, ?, 'rental', ?, ?, 'onhold', ?)
            ", [$order_id, $payment_id, $order['customer_id'], $order['vendor_user_id'], 
                $vendor_earning, $total_amount, $source]);
            
            // Record 3: Admin commission
            $this->db->execute("
                INSERT INTO order_payment_breakdown 
                (order_id, payment_id, customer_id, user_id, type, amount, total_amount, status, source)
                VALUES (?, ?, ?, ?, 'platform_commission', ?, ?, 'onhold', ?)
            ", [$order_id, $payment_id, $order['customer_id'], $admin_user_id, 
                $platform_commission, $total_amount, $source]);
            
            // ========================================
            // UPDATE WALLET - Customer security onhold
            // ========================================
            $customer_wallet = $this->getOrCreateWallet($order['customer_user_id'], 'customer');
            
            $this->db->execute("
                UPDATE wallets 
                SET security_onhold = security_onhold + ?
                WHERE id = ?
            ", [$security_deposit, $customer_wallet['id']]);
            
            // ========================================
            // CREATE wallet_transactions - Security held
            // ========================================
            $balance_before = floatval($customer_wallet['security_onhold']);
            $balance_after = $balance_before + $security_deposit;
            $reference = 'SEC-HOLD-' . $order_id . '-' . time();
            
            $this->db->execute("
                INSERT INTO wallet_transactions 
                (user_id, wallet_id, order_id, breakdown_id, transaction_type, category, 
                 amount, balance_before, balance_after, description, reference, status)
                VALUES (?, ?, ?, ?, 'security_deposit_held', 'debit', ?, ?, ?, 
                        'Security deposit held for order', ?, 'completed')
            ", [$order['customer_user_id'], $customer_wallet['id'], $order_id, $security_breakdown_id,
                $security_deposit, $balance_before, $balance_after, $reference]);
            
            $this->db->commit();
            return true;
            
        } catch (Exception $e) {
            if ($this->db->inTransaction()) $this->db->rollback();
            error_log("WalletProcessor::processPayment ERROR: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Process completed order - called from complete-rental.php
     * Changes order_payment_breakdown status to 'released'
     * Creates 3 wallet_transactions
     * Updates all wallets
     */
    public function processCompletedOrder($order_id) {
        try {
            $this->db->beginTransaction();
            
            // Get breakdown records
            $breakdowns = $this->db->fetchAll("
                SELECT * FROM order_payment_breakdown 
                WHERE order_id = ? AND status = 'onhold'
            ", [$order_id]);
            
            if (empty($breakdowns)) {
                throw new Exception("No onhold breakdown found for order #{$order_id}");
            }
            
            // Update all 3 breakdown records to 'released'
            $this->db->execute("
                UPDATE order_payment_breakdown 
                SET status = 'released', updated_at = NOW()
                WHERE order_id = ? AND status = 'onhold'
            ", [$order_id]);
            
            // Process each breakdown record
            foreach ($breakdowns as $breakdown) {
                $user_id = $breakdown['user_id'];
                $type = $breakdown['type'];
                $amount = floatval($breakdown['amount']);
                
                $wallet = $this->getOrCreateWallet($user_id, null);
                
                if ($type === 'security_deposit') {
                    // Customer: security_onhold → balance
                    $sec_before = floatval($wallet['security_onhold']);
                    $bal_before = floatval($wallet['balance']);
                    
                    $this->db->execute("
                        UPDATE wallets 
                        SET security_onhold = security_onhold - ?,
                            balance = balance + ?
                        WHERE id = ?
                    ", [$amount, $amount, $wallet['id']]);
                    
                    $reference = 'SEC-REFUND-' . $order_id . '-' . time();
                    
                    $this->db->execute("
                        INSERT INTO wallet_transactions 
                        (user_id, wallet_id, order_id, breakdown_id, transaction_type, category, 
                         amount, balance_before, balance_after, description, reference, status)
                        VALUES (?, ?, ?, ?, 'security_deposit_refund', 'credit', ?, ?, ?, 
                                'Security deposit refunded', ?, 'completed')
                    ", [$user_id, $wallet['id'], $order_id, $breakdown['id'],
                        $amount, $bal_before, $bal_before + $amount, $reference]);
                    
                } elseif ($type === 'rental') {
                    // Vendor: earnings_onhold → balance
                    $bal_before = floatval($wallet['balance']);
                    
                    $this->db->execute("
                        UPDATE wallets 
                        SET balance = balance + ?,
                            total_earned = total_earned + ?
                        WHERE id = ?
                    ", [$amount, $amount, $wallet['id']]);
                    
                    $reference = 'VEND-EARN-' . $order_id . '-' . time();
                    
                    $this->db->execute("
                        INSERT INTO wallet_transactions 
                        (user_id, wallet_id, order_id, breakdown_id, transaction_type, category, 
                         amount, balance_before, balance_after, description, reference, status)
                        VALUES (?, ?, ?, ?, 'rental_earning', 'credit', ?, ?, ?, 
                                'Rental earning released', ?, 'completed')
                    ", [$user_id, $wallet['id'], $order_id, $breakdown['id'],
                        $amount, $bal_before, $bal_before + $amount, $reference]);
                    
                } elseif ($type === 'platform_commission') {
                    // Admin: commission
                    $bal_before = floatval($wallet['balance']);
                    
                    $this->db->execute("
                        UPDATE wallets 
                        SET balance = balance + ?,
                            total_earned = total_earned + ?
                        WHERE id = ?
                    ", [$amount, $amount, $wallet['id']]);
                    
                    $reference = 'COMM-EARN-' . $order_id . '-' . time();
                    
                    $this->db->execute("
                        INSERT INTO wallet_transactions 
                        (user_id, wallet_id, order_id, breakdown_id, transaction_type, category, 
                         amount, balance_before, balance_after, description, reference, status)
                        VALUES (?, ?, ?, ?, 'platform_commission', 'credit', ?, ?, ?, 
                                'Platform commission earned', ?, 'completed')
                    ", [$user_id, $wallet['id'], $order_id, $breakdown['id'],
                        $amount, $bal_before, $bal_before + $amount, $reference]);
                }
            }
            
            $this->db->commit();
            return true;
            
        } catch (Exception $e) {
            if ($this->db->inTransaction()) $this->db->rollback();
            error_log("WalletProcessor::processCompletedOrder ERROR: " . $e->getMessage());
            throw $e;
        }
    }
    
    /**
     * Process cancellation - called from cancel-order.php
     * Changes breakdown status to 'refunded'
     * Returns full amount to customer
     */
    public function processCancellation($order_id) {
        try {
            $this->db->beginTransaction();
            
            // Get breakdown records
            $breakdowns = $this->db->fetchAll("
                SELECT * FROM order_payment_breakdown 
                WHERE order_id = ? AND status = 'onhold'
            ", [$order_id]);
            
            if (empty($breakdowns)) {
                throw new Exception("No onhold breakdown found for order #{$order_id}");
            }
            
            // Get customer and total
            $customer_breakdown = array_filter($breakdowns, fn($b) => $b['type'] === 'security_deposit');
            $customer_breakdown = reset($customer_breakdown);
            
            $customer_id = $customer_breakdown['customer_id'];
            $customer_user_id = $customer_breakdown['user_id'];
            $total_amount = floatval($customer_breakdown['total_amount']);
            $security_amount = floatval($customer_breakdown['amount']);
            
            // Update all breakdowns to 'refunded'
            $this->db->execute("
                UPDATE order_payment_breakdown 
                SET status = 'cancelled', updated_at = NOW()
                WHERE order_id = ?
            ", [$order_id]);
            
            // Get customer wallet
            $wallet = $this->getOrCreateWallet($customer_user_id, 'customer');
            
            // Return security onhold + full refund
            $bal_before = floatval($wallet['balance']);
            
            $this->db->execute("
                UPDATE wallets 
                SET security_onhold = security_onhold - ?,
                    balance = balance + ?
                WHERE id = ?
            ", [$security_amount, $total_amount, $wallet['id']]);
            
            $reference = 'CANCEL-REFUND-' . $order_id . '-' . time();
            
            $this->db->execute("
                INSERT INTO wallet_transactions 
                (user_id, wallet_id, order_id, transaction_type, category, 
                 amount, balance_before, balance_after, description, reference, status)
                VALUES (?, ?, ?, 'cancellation_refund', 'credit', ?, ?, ?, 
                        'Full refund - Order cancelled', ?, 'completed')
            ", [$customer_user_id, $wallet['id'], $order_id,
                $total_amount, $bal_before, $bal_before + $total_amount, $reference]);
            
            $this->db->commit();
            return true;
            
        } catch (Exception $e) {
            if ($this->db->inTransaction()) $this->db->rollback();
            error_log("WalletProcessor::processCancellation ERROR: " . $e->getMessage());
            throw $e;
        }
    }
    
    /**
     * Get or create wallet
     */
    private function getOrCreateWallet($user_id, $user_type) {
        $wallet = $this->db->fetch("SELECT * FROM wallets WHERE user_id = ?", [$user_id]);
        
        if (!$wallet) {
            if (!$user_type) {
                $user = $this->db->fetch("SELECT user_type FROM users WHERE id = ?", [$user_id]);
                $user_type = $user['user_type'];
            }
            
            $this->db->execute("
                INSERT INTO wallets (user_id, user_type) VALUES (?, ?)
            ", [$user_id, $user_type]);
            
            $wallet = $this->db->fetch("SELECT * FROM wallets WHERE user_id = ?", [$user_id]);
        }
        
        return $wallet;
    }
}