<?php
/**
 * WalletService - Manages multi-wallet operations
 * Location: app/Services/WalletService.php
 */
class WalletService {
    private $db;
    private $user_id;
    
    public function __construct($user_id = null) {
        $this->db = Database::getInstance()->getConnection();
        $this->user_id = $user_id;
    }
    
    /**
     * Initialize wallets for new user
     */
    public function initializeUserWallets($user_id, $user_type) {
        $wallets = [];
        
        if ($user_type === 'customer') {
            $wallets = ['main_balance', 'security_held', 'security_refundable'];
        } elseif ($user_type === 'vendor') {
            $wallets = ['main_balance', 'pending_earnings'];
        }
        
        $stmt = $this->db->prepare("
            INSERT INTO user_wallets (user_id, wallet_type, balance) 
            VALUES (?, ?, 0.00)
        ");
        
        foreach ($wallets as $wallet_type) {
            $stmt->bind_param("is", $user_id, $wallet_type);
            $stmt->execute();
        }
        
        return true;
    }
    
    /**
     * Get user's wallet by type
     */
    public function getWallet($user_id, $wallet_type) {
        $stmt = $this->db->prepare("
            SELECT * FROM user_wallets 
            WHERE user_id = ? AND wallet_type = ?
        ");
        $stmt->bind_param("is", $user_id, $wallet_type);
        $stmt->execute();
        $result = $stmt->get_result();
        return $result->fetch_assoc();
    }
    
    /**
     * Get all wallets for user
     */
    public function getAllWallets($user_id) {
        $stmt = $this->db->prepare("
            SELECT * FROM user_wallets WHERE user_id = ?
        ");
        $stmt->bind_param("i", $user_id);
        $stmt->execute();
        $result = $stmt->get_result();
        
        $wallets = [];
        while ($row = $result->fetch_assoc()) {
            $wallets[$row['wallet_type']] = $row;
        }
        return $wallets;
    }
    
    /**
     * Get customer dashboard wallet summary
     */
    public function getCustomerWalletSummary($user_id) {
        $wallets = $this->getAllWallets($user_id);
        
        // Calculate total spent (from transactions)
        $stmt = $this->db->prepare("
            SELECT COALESCE(SUM(amount), 0) as total_spent 
            FROM transactions 
            WHERE user_id = ? 
            AND transaction_type = 'rental_payment' 
            AND status = 'completed'
        ");
        $stmt->bind_param("i", $user_id);
        $stmt->execute();
        $total_spent = $stmt->get_result()->fetch_assoc()['total_spent'];
        
        return [
            'main_balance' => $wallets['main_balance']['balance'] ?? 0,
            'security_held' => $wallets['security_held']['balance'] ?? 0,
            'security_refundable' => $wallets['security_refundable']['balance'] ?? 0,
            'total_spent' => $total_spent
        ];
    }
    
    /**
     * Get vendor dashboard wallet summary
     */
    public function getVendorWalletSummary($user_id) {
        $wallets = $this->getAllWallets($user_id);
        
        // Calculate total earnings
        $stmt = $this->db->prepare("
            SELECT COALESCE(SUM(amount), 0) as total_earnings 
            FROM transactions 
            WHERE user_id = ? 
            AND transaction_type = 'vendor_earning' 
            AND status = 'completed'
        ");
        $stmt->bind_param("i", $user_id);
        $stmt->execute();
        $total_earnings = $stmt->get_result()->fetch_assoc()['total_earnings'];
        
        return [
            'main_balance' => $wallets['main_balance']['balance'] ?? 0,
            'pending_earnings' => $wallets['pending_earnings']['balance'] ?? 0,
            'total_earnings' => $total_earnings
        ];
    }
    
    /**
     * Process wallet top-up
     */
    public function topUp($user_id, $amount, $payment_reference) {
        $this->db->begin_transaction();
        
        try {
            $wallet = $this->getWallet($user_id, 'main_balance');
            
            if (!$wallet) {
                throw new Exception("Wallet not found");
            }
            
            $new_balance = $wallet['balance'] + $amount;
            
            // Update wallet balance
            $stmt = $this->db->prepare("
                UPDATE user_wallets 
                SET balance = ? 
                WHERE id = ?
            ");
            $stmt->bind_param("di", $new_balance, $wallet['id']);
            $stmt->execute();
            
            // Record transaction
            $reference = 'TOP_' . strtoupper(uniqid());
            $this->recordTransaction([
                'user_id' => $user_id,
                'to_wallet_id' => $wallet['id'],
                'transaction_type' => 'top_up',
                'amount' => $amount,
                'balance_before' => $wallet['balance'],
                'balance_after' => $new_balance,
                'description' => "Wallet top-up via {$payment_reference}",
                'reference' => $reference,
                'status' => 'completed'
            ]);
            
            $this->db->commit();
            return ['success' => true, 'new_balance' => $new_balance];
            
        } catch (Exception $e) {
            $this->db->rollback();
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
    
    /**
     * Process rental payment from customer
     */
    public function processRentalPayment($customer_id, $vendor_id, $order_id, $rental_amount, $security_deposit, $payment_method = 'online') {
        $this->db->begin_transaction();
        
        try {
            $total_amount = $rental_amount + $security_deposit;
            
            // Deduct from customer's main wallet if using wallet
            $customer_wallet = $this->getWallet($customer_id, 'main_balance');
            
            if ($payment_method === 'wallet' && $customer_wallet['balance'] < $total_amount) {
                throw new Exception("Insufficient wallet balance");
            }
            
            // Move security deposit to held
            $security_wallet = $this->getWallet($customer_id, 'security_held');
            $this->transferBetweenWallets(
                $customer_id,
                $customer_wallet['id'],
                $security_wallet['id'],
                $security_deposit,
                'security_deposit',
                "Security deposit for order #{$order_id}",
                $order_id
            );
            
            // Transfer rental amount to vendor's pending earnings
            $vendor_wallet = $this->getWallet($vendor_id, 'pending_earnings');
            $this->recordTransaction([
                'user_id' => $vendor_id,
                'to_wallet_id' => $vendor_wallet['id'],
                'order_id' => $order_id,
                'transaction_type' => 'rental_payment',
                'amount' => $rental_amount,
                'balance_before' => $vendor_wallet['balance'],
                'balance_after' => $vendor_wallet['balance'] + $rental_amount,
                'description' => "Rental payment for order #{$order_id}",
                'reference' => 'RENT_' . $order_id . '_' . time(),
                'status' => 'completed'
            ]);
            
            // Update vendor wallet
            $stmt = $this->db->prepare("
                UPDATE user_wallets 
                SET balance = balance + ? 
                WHERE id = ?
            ");
            $stmt->bind_param("di", $rental_amount, $vendor_wallet['id']);
            $stmt->execute();
            
            $this->db->commit();
            return ['success' => true];
            
        } catch (Exception $e) {
            $this->db->rollback();
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
    
    /**
     * Complete rental and release funds
     */
    public function completeRental($order_id, $vendor_id, $customer_id, $security_deposit, $rental_amount, $commission_rate = 5) {
        $this->db->begin_transaction();
        
        try {
            // Calculate commission
            $commission = ($rental_amount * $commission_rate) / 100;
            $vendor_net = $rental_amount - $commission;
            
            // Move vendor funds from pending to main balance
            $vendor_pending = $this->getWallet($vendor_id, 'pending_earnings');
            $vendor_main = $this->getWallet($vendor_id, 'main_balance');
            
            $this->transferBetweenWallets(
                $vendor_id,
                $vendor_pending['id'],
                $vendor_main['id'],
                $vendor_net,
                'vendor_earning',
                "Rental completed - Order #{$order_id}",
                $order_id
            );
            
            // Deduct commission to platform
            $this->deductCommission($vendor_id, $vendor_pending['id'], $commission, $order_id);
            
            // Move customer security deposit from held to refundable
            $customer_held = $this->getWallet($customer_id, 'security_held');
            $customer_refundable = $this->getWallet($customer_id, 'security_refundable');
            
            $this->transferBetweenWallets(
                $customer_id,
                $customer_held['id'],
                $customer_refundable['id'],
                $security_deposit,
                'security_transfer',
                "Security deposit released - Order #{$order_id}",
                $order_id
            );
            
            // Update order status
            $stmt = $this->db->prepare("
                UPDATE orders 
                SET rental_completed = 1, 
                    completed_at = NOW(), 
                    security_deposit_status = 'released' 
                WHERE id = ?
            ");
            $stmt->bind_param("i", $order_id);
            $stmt->execute();
            
            $this->db->commit();
            return ['success' => true];
            
        } catch (Exception $e) {
            $this->db->rollback();
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
    
    /**
     * Transfer between wallets
     */
    private function transferBetweenWallets($user_id, $from_wallet_id, $to_wallet_id, $amount, $type, $description, $order_id = null) {
        // Get current balances
        $stmt = $this->db->prepare("SELECT balance FROM user_wallets WHERE id = ?");
        
        $stmt->bind_param("i", $from_wallet_id);
        $stmt->execute();
        $from_balance = $stmt->get_result()->fetch_assoc()['balance'];
        
        $stmt->bind_param("i", $to_wallet_id);
        $stmt->execute();
        $to_balance = $stmt->get_result()->fetch_assoc()['balance'];
        
        if ($from_balance < $amount) {
            throw new Exception("Insufficient balance in source wallet");
        }
        
        // Deduct from source
        $stmt = $this->db->prepare("UPDATE user_wallets SET balance = balance - ? WHERE id = ?");
        $stmt->bind_param("di", $amount, $from_wallet_id);
        $stmt->execute();
        
        // Add to destination
        $stmt = $this->db->prepare("UPDATE user_wallets SET balance = balance + ? WHERE id = ?");
        $stmt->bind_param("di", $amount, $to_wallet_id);
        $stmt->execute();
        
        // Record transaction
        $this->recordTransaction([
            'user_id' => $user_id,
            'from_wallet_id' => $from_wallet_id,
            'to_wallet_id' => $to_wallet_id,
            'order_id' => $order_id,
            'transaction_type' => $type,
            'amount' => $amount,
            'balance_before' => $from_balance,
            'balance_after' => $from_balance - $amount,
            'description' => $description,
            'reference' => strtoupper($type) . '_' . time() . '_' . rand(1000, 9999),
            'status' => 'completed'
        ]);
    }
    
    /**
     * Deduct platform commission
     */
    private function deductCommission($vendor_id, $wallet_id, $commission, $order_id) {
        $stmt = $this->db->prepare("
            UPDATE user_wallets 
            SET balance = balance - ? 
            WHERE id = ?
        ");
        $stmt->bind_param("di", $commission, $wallet_id);
        $stmt->execute();
        
        // Record commission transaction
        $this->recordTransaction([
            'user_id' => $vendor_id,
            'from_wallet_id' => $wallet_id,
            'order_id' => $order_id,
            'transaction_type' => 'commission',
            'amount' => $commission,
            'balance_before' => 0,
            'balance_after' => 0,
            'description' => "Platform commission - Order #{$order_id}",
            'reference' => 'COMM_' . $order_id . '_' . time(),
            'status' => 'completed'
        ]);
        
        // Update platform wallet
        $stmt = $this->db->prepare("
            UPDATE platform_wallet 
            SET balance = balance + ?, 
                total_commissions = total_commissions + ?
        ");
        $stmt->bind_param("dd", $commission, $commission);
        $stmt->execute();
    }
    
    /**
     * Record transaction in ledger
     */
    public function recordTransaction($data) {
        $stmt = $this->db->prepare("
            INSERT INTO transactions 
            (user_id, from_wallet_id, to_wallet_id, order_id, transaction_type, amount, 
             balance_before, balance_after, description, reference, metadata, status) 
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
        ");
        
        $stmt->bind_param(
            "iiiisdddssss",
            $data['user_id'],
            $data['from_wallet_id'] ?? null,
            $data['to_wallet_id'] ?? null,
            $data['order_id'] ?? null,
            $data['transaction_type'],
            $data['amount'],
            $data['balance_before'],
            $data['balance_after'],
            $data['description'],
            $data['reference'],
            $data['metadata'] ?? null,
            $data['status']
        );
        
        return $stmt->execute();
    }
    
    /**
     * Get user transaction history
     */
    public function getTransactionHistory($user_id, $limit = 50, $offset = 0) {
        $stmt = $this->db->prepare("
            SELECT t.*, 
                   fw.wallet_type as from_wallet_type,
                   tw.wallet_type as to_wallet_type,
                   o.order_number
            FROM transactions t
            LEFT JOIN user_wallets fw ON t.from_wallet_id = fw.id
            LEFT JOIN user_wallets tw ON t.to_wallet_id = tw.id
            LEFT JOIN orders o ON t.order_id = o.id
            WHERE t.user_id = ?
            ORDER BY t.created_at DESC
            LIMIT ? OFFSET ?
        ");
        $stmt->bind_param("iii", $user_id, $limit, $offset);
        $stmt->execute();
        return $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
    }
}
