<?php
/**
 * PaymentProcessor Class
 * File: app/Services/PaymentProcessor.php
 * 
 * Handles automated payment distribution and wallet synchronization
 * This is the CORE logic that keeps everything in sync
 */

class PaymentProcessor {
    private $db;
    private $wallet;
    private $onlinePayment;
    private $walletTransaction;
    
    public function __construct() {
        $this->db = Database::getInstance();
        $this->wallet = new Wallet();
        $this->onlinePayment = new OnlinePayment();
        $this->walletTransaction = new WalletTransaction();
    }
    
    /**
     * Process completed rental order
     * Called when vendor approves order completion
     * 
     * @param array $order Order details
     * @return bool Success status
     */
    public function processCompletedOrder($order) {
        $this->db->beginTransaction();
        
        try {
            // Get commission settings
            $commission_percentage = $this->getCommissionPercentage($order['vendor_id']);
            
            // Calculate amounts
            $rental_amount = floatval($order['subtotal']);
            $security_deposit = floatval($order['security_deposit']);
            $platform_fee = ($rental_amount * $commission_percentage) / 100;
            $vendor_earning = $rental_amount - $platform_fee;
            
            // Get user IDs
            $vendor_user_id = $this->getVendorUserId($order['vendor_id']);
            $customer_user_id = $this->getCustomerUserId($order['customer_id']);
            
            // Generate references
            $vendor_ref = 'VEND-' . $order['order_number'] . '-' . time();
            $customer_ref = 'REFD-' . $order['order_number'] . '-' . time();
            $commission_ref = 'COMM-' . $order['order_number'] . '-' . time();
            
            // 1. Credit vendor wallet (rental amount minus platform fee)
            $vendor_credit = $this->wallet->credit(
                $vendor_user_id,
                $vendor_earning,
                'vendor_earning',
                "Rental earning for order #{$order['order_number']} (₦{$rental_amount} - ₦{$platform_fee} commission)",
                $vendor_ref,
                $order['id']
            );
            
            if (!$vendor_credit) {
                throw new Exception("Failed to credit vendor wallet");
            }
            
            // 2. Refund security deposit to customer
            if ($security_deposit > 0) {
                $customer_credit = $this->wallet->credit(
                    $customer_user_id,
                    $security_deposit,
                    'security_refund',
                    "Security deposit refund for order #{$order['order_number']}",
                    $customer_ref,
                    $order['id']
                );
                
                if (!$customer_credit) {
                    throw new Exception("Failed to refund security deposit to customer");
                }
            }
            
            // 3. Credit platform wallet (commission)
            $platform_user_id = 1; // Admin user ID
            $commission_credit = $this->wallet->credit(
                $platform_user_id,
                $platform_fee,
                'commission',
                "Platform commission for order #{$order['order_number']} ({$commission_percentage}% of ₦{$rental_amount})",
                $commission_ref,
                $order['id']
            );
            
            if (!$commission_credit) {
                throw new Exception("Failed to credit platform commission");
            }
            
            // 4. Record commission in commissions table
            $this->recordCommission($order, $commission_percentage, $platform_fee, $vendor_earning);
            
            // 5. Update order security deposit status
            $this->updateOrderSecurityStatus($order['id'], 'released');
            
            // 6. Send notifications
            $this->sendVendorEarningNotification($order, $vendor_earning);
            $this->sendSecurityRefundNotification($order, $security_deposit);
            
            $this->db->commit();
            
            error_log("Payment processed successfully for order #{$order['order_number']}");
            return true;
            
        } catch (Exception $e) {
            $this->db->rollback();
            error_log("Payment processing error for order #{$order['order_number']}: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Process successful online payment
     * Called after Paystack webhook confirms payment
     * 
     * @param string $transaction_reference Payment reference
     * @return bool Success status
     */
    public function processSuccessfulPayment($transaction_reference) {
        $this->db->beginTransaction();
        
        try {
            // Get payment details
            $payment = $this->onlinePayment->findByReference($transaction_reference);
            
            if (!$payment) {
                throw new Exception("Payment not found");
            }
            
            if ($payment['status'] === 'successful') {
                // Already processed
                return true;
            }
            
            // Mark payment as successful
            $this->onlinePayment->updateStatus($transaction_reference, 'successful', [
                'gateway_reference' => $payment['gateway_reference'] ?? null
            ]);
            
            // If it's a wallet top-up, credit the customer wallet
            if ($payment['payment_type'] === 'wallet_topup') {
                $customer_user_id = $this->getCustomerUserId($payment['customer_id']);
                
                $this->wallet->credit(
                    $customer_user_id,
                    $payment['amount'],
                    'top_up',
                    "Wallet top-up via {$payment['payment_gateway']}",
                    $transaction_reference
                );
            }
            
            // Update order payment status if linked to an order
            if ($payment['order_id']) {
                $this->updateOrderPaymentStatus($payment['order_id'], 'paid');
            }
            
            $this->db->commit();
            return true;
            
        } catch (Exception $e) {
            $this->db->rollback();
            error_log("Payment success processing error: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Process withdrawal request
     * 
     * @param int $withdrawal_id Withdrawal request ID
     * @param int $admin_id Admin processing the withdrawal
     * @return bool Success status
     */
    public function processWithdrawal($withdrawal_id, $admin_id) {
        $this->db->beginTransaction();
        
        try {
            $withdrawal = new Withdrawal();
            $request = $withdrawal->find($withdrawal_id);
            
            if (!$request || $request['status'] !== 'pending') {
                throw new Exception("Invalid withdrawal request");
            }
            
            // Debit user wallet
            $debit_success = $this->wallet->debit(
                $request['user_id'],
                $request['amount'],
                'withdrawal',
                "Withdrawal to {$request['bank_name']} - {$request['account_number']}",
                $request['reference']
            );
            
            if (!$debit_success) {
                throw new Exception("Failed to debit wallet");
            }
            
            // Get transaction ID
            $transaction = $this->walletTransaction->getByReference($request['reference']);
            
            // Mark withdrawal as paid
            $withdrawal->markAsPaid($withdrawal_id, $admin_id, $transaction['id'] ?? null);
            
            $this->db->commit();
            
            // Send notification
            $this->sendWithdrawalNotification($request);
            
            return true;
            
        } catch (Exception $e) {
            $this->db->rollback();
            error_log("Withdrawal processing error: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Process order cancellation refund
     * 
     * @param array $order Order details
     * @param string $cancelled_by Who cancelled (customer/vendor/admin)
     * @return bool Success status
     */
    public function processCancellationRefund($order, $cancelled_by) {
        $this->db->beginTransaction();
        
        try {
            $customer_user_id = $this->getCustomerUserId($order['customer_id']);
            
            // Full refund if order is cancelled before confirmation
            if ($order['status'] === 'pending') {
                $refund_amount = floatval($order['total_amount']);
                
                $this->wallet->credit(
                    $customer_user_id,
                    $refund_amount,
                    'cancellation_refund',
                    "Full refund for cancelled order #{$order['order_number']}",
                    'CNCL-' . $order['order_number'] . '-' . time(),
                    $order['id']
                );
            }
            // Partial refund based on cancellation policy
            else {
                // You can implement your cancellation policy here
                // For now, refund security deposit only
                if (floatval($order['security_deposit']) > 0) {
                    $this->wallet->credit(
                        $customer_user_id,
                        $order['security_deposit'],
                        'cancellation_refund',
                        "Security deposit refund for cancelled order #{$order['order_number']}",
                        'CNCL-' . $order['order_number'] . '-' . time(),
                        $order['id']
                    );
                }
            }
            
            // Update order payment status
            $this->updateOrderPaymentStatus($order['id'], 'refunded');
            
            $this->db->commit();
            return true;
            
        } catch (Exception $e) {
            $this->db->rollback();
            error_log("Cancellation refund error: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Get commission percentage for vendor
     */
    private function getCommissionPercentage($vendor_id) {
        $sql = "SELECT commission_rate FROM vendors WHERE id = ? LIMIT 1";
        $result = $this->db->fetch($sql, [$vendor_id]);
        
        // Default to 10% if not set
        return $result['commission_rate'] ?? 10;
    }
    
    /**
     * Get vendor user ID
     */
    private function getVendorUserId($vendor_id) {
        $sql = "SELECT user_id FROM vendors WHERE id = ? LIMIT 1";
        $result = $this->db->fetch($sql, [$vendor_id]);
        return $result['user_id'] ?? null;
    }
    
    /**
     * Get customer user ID
     */
    private function getCustomerUserId($customer_id) {
        $sql = "SELECT user_id FROM customers WHERE id = ? LIMIT 1";
        $result = $this->db->fetch($sql, [$customer_id]);
        return $result['user_id'] ?? null;
    }
    
    /**
     * Record commission in commissions table
     */
    private function recordCommission($order, $commission_percentage, $commission_amount, $vendor_amount) {
        $sql = "INSERT INTO commissions (
                order_id, vendor_id, order_amount, commission_percentage, 
                commission_amount, vendor_amount, status, paid_at, created_at
                ) VALUES (?, ?, ?, ?, ?, ?, 'paid', NOW(), NOW())";
        
        return $this->db->execute($sql, [
            $order['id'],
            $order['vendor_id'],
            $order['subtotal'],
            $commission_percentage,
            $commission_amount,
            $vendor_amount
        ]);
    }
    
    /**
     * Update order security deposit status
     */
    private function updateOrderSecurityStatus($order_id, $status) {
        $sql = "UPDATE orders SET security_deposit_status = ?, updated_at = NOW() WHERE id = ?";
        return $this->db->execute($sql, [$status, $order_id]);
    }
    
    /**
     * Update order payment status
     */
    private function updateOrderPaymentStatus($order_id, $status) {
        $sql = "UPDATE orders SET payment_status = ?, updated_at = NOW() WHERE id = ?";
        return $this->db->execute($sql, [$status, $order_id]);
    }
    
    /**
     * Send vendor earning notification
     */
    private function sendVendorEarningNotification($order, $amount) {
        // Implement your notification logic here
        // Email, SMS, or in-app notification
        error_log("Vendor earning notification sent for order #{$order['order_number']}: ₦{$amount}");
    }
    
    /**
     * Send security refund notification
     */
    private function sendSecurityRefundNotification($order, $amount) {
        // Implement your notification logic here
        error_log("Security refund notification sent for order #{$order['order_number']}: ₦{$amount}");
    }
    
    /**
     * Send withdrawal notification
     */
    private function sendWithdrawalNotification($request) {
        // Implement your notification logic here
        error_log("Withdrawal processed: ₦{$request['amount']} to {$request['account_number']}");
    }
}