<?php
require_once 'Database.php';
require_once 'Security.php';

class Wallet {
    private $db;
    
    public function __construct() {
        $this->db = new Database();
    }
    
    // Get user wallets
    public function getUserWallets($userId) {
        $this->db->query("SELECT w.*, c.symbol, c.name, c.current_price 
                         FROM wallets w 
                         JOIN cryptocurrencies c ON w.crypto_id = c.id 
                         WHERE w.user_id = :user_id AND c.is_active = 1
                         ORDER BY c.symbol");
        $this->db->bind(':user_id', $userId);
        return $this->db->resultSet();
    }
    
    // Get specific wallet
    public function getWallet($userId, $cryptoId) {
        $this->db->query("SELECT w.*, c.symbol, c.name, c.current_price 
                         FROM wallets w 
                         JOIN cryptocurrencies c ON w.crypto_id = c.id 
                         WHERE w.user_id = :user_id AND w.crypto_id = :crypto_id");
        $this->db->bind(':user_id', $userId);
        $this->db->bind(':crypto_id', $cryptoId);
        return $this->db->single();
    }
    
    // Get wallet balance
    public function getBalance($userId, $cryptoId) {
        $this->db->query("SELECT balance FROM wallets WHERE user_id = :user_id AND crypto_id = :crypto_id");
        $this->db->bind(':user_id', $userId);
        $this->db->bind(':crypto_id', $cryptoId);
        $result = $this->db->single();
        return $result ? $result['balance'] : 0;
    }
    
    // Add funds to wallet (for testing/admin)
    public function addFunds($userId, $cryptoId, $amount, $description = 'Admin deposit') {
        try {
            $this->db->beginTransaction();
            
            // Get current balance
            $currentBalance = $this->getBalance($userId, $cryptoId);
            $newBalance = $currentBalance + $amount;
            
            // Update wallet balance
            $this->db->query("UPDATE wallets SET balance = :balance WHERE user_id = :user_id AND crypto_id = :crypto_id");
            $this->db->bind(':balance', $newBalance);
            $this->db->bind(':user_id', $userId);
            $this->db->bind(':crypto_id', $cryptoId);
            
            if (!$this->db->execute()) {
                throw new Exception('Failed to update wallet balance');
            }
            
            // Record transaction
            $this->recordTransaction($userId, $cryptoId, 'deposit', $amount, $currentBalance, $newBalance, null, null, $description);
            
            $this->db->endTransaction();
            
            Security::logSecurityEvent('FUNDS_ADDED', "Added $amount to wallet", $userId);
            
            return ['success' => true, 'message' => 'Funds added successfully', 'new_balance' => $newBalance];
            
        } catch (Exception $e) {
            $this->db->cancelTransaction();
            error_log('Add funds error: ' . $e->getMessage());
            return ['success' => false, 'message' => 'Failed to add funds'];
        }
    }
    
    // Lock funds for trading
    public function lockFunds($userId, $cryptoId, $amount) {
        try {
            $this->db->beginTransaction();
            
            // Get current balances
            $wallet = $this->getWallet($userId, $cryptoId);
            
            if (!$wallet || $wallet['balance'] < $amount) {
                throw new Exception('Insufficient balance');
            }
            
            // Update balances
            $newBalance = $wallet['balance'] - $amount;
            $newLockedBalance = $wallet['locked_balance'] + $amount;
            
            $this->db->query("UPDATE wallets SET balance = :balance, locked_balance = :locked_balance 
                             WHERE user_id = :user_id AND crypto_id = :crypto_id");
            $this->db->bind(':balance', $newBalance);
            $this->db->bind(':locked_balance', $newLockedBalance);
            $this->db->bind(':user_id', $userId);
            $this->db->bind(':crypto_id', $cryptoId);
            
            if (!$this->db->execute()) {
                throw new Exception('Failed to lock funds');
            }
            
            $this->db->endTransaction();
            
            return ['success' => true, 'message' => 'Funds locked successfully'];
            
        } catch (Exception $e) {
            $this->db->cancelTransaction();
            error_log('Lock funds error: ' . $e->getMessage());
            return ['success' => false, 'message' => $e->getMessage()];
        }
    }
    
    // Unlock funds
    public function unlockFunds($userId, $cryptoId, $amount) {
        try {
            $this->db->beginTransaction();
            
            // Get current balances
            $wallet = $this->getWallet($userId, $cryptoId);
            
            if (!$wallet || $wallet['locked_balance'] < $amount) {
                throw new Exception('Insufficient locked balance');
            }
            
            // Update balances
            $newBalance = $wallet['balance'] + $amount;
            $newLockedBalance = $wallet['locked_balance'] - $amount;
            
            $this->db->query("UPDATE wallets SET balance = :balance, locked_balance = :locked_balance 
                             WHERE user_id = :user_id AND crypto_id = :crypto_id");
            $this->db->bind(':balance', $newBalance);
            $this->db->bind(':locked_balance', $newLockedBalance);
            $this->db->bind(':user_id', $userId);
            $this->db->bind(':crypto_id', $cryptoId);
            
            if (!$this->db->execute()) {
                throw new Exception('Failed to unlock funds');
            }
            
            $this->db->endTransaction();
            
            return ['success' => true, 'message' => 'Funds unlocked successfully'];
            
        } catch (Exception $e) {
            $this->db->cancelTransaction();
            error_log('Unlock funds error: ' . $e->getMessage());
            return ['success' => false, 'message' => $e->getMessage()];
        }
    }
    
    // Transfer funds between wallets
    public function transferFunds($fromUserId, $toUserId, $cryptoId, $amount, $referenceType = null, $referenceId = null) {
        try {
            $this->db->beginTransaction();
            
            // Get sender wallet
            $fromWallet = $this->getWallet($fromUserId, $cryptoId);
            if (!$fromWallet || $fromWallet['locked_balance'] < $amount) {
                throw new Exception('Insufficient locked balance');
            }
            
            // Get receiver wallet
            $toWallet = $this->getWallet($toUserId, $cryptoId);
            if (!$toWallet) {
                throw new Exception('Receiver wallet not found');
            }
            
            // Update sender wallet
            $newFromLockedBalance = $fromWallet['locked_balance'] - $amount;
            $this->db->query("UPDATE wallets SET locked_balance = :locked_balance 
                             WHERE user_id = :user_id AND crypto_id = :crypto_id");
            $this->db->bind(':locked_balance', $newFromLockedBalance);
            $this->db->bind(':user_id', $fromUserId);
            $this->db->bind(':crypto_id', $cryptoId);
            
            if (!$this->db->execute()) {
                throw new Exception('Failed to update sender wallet');
            }
            
            // Update receiver wallet
            $newToBalance = $toWallet['balance'] + $amount;
            $this->db->query("UPDATE wallets SET balance = :balance 
                             WHERE user_id = :user_id AND crypto_id = :crypto_id");
            $this->db->bind(':balance', $newToBalance);
            $this->db->bind(':user_id', $toUserId);
            $this->db->bind(':crypto_id', $cryptoId);
            
            if (!$this->db->execute()) {
                throw new Exception('Failed to update receiver wallet');
            }
            
            // Record transactions
            $this->recordTransaction($fromUserId, $cryptoId, 'trade_sell', -$amount, 
                                   $fromWallet['balance'], $fromWallet['balance'], 
                                   $referenceType, $referenceId, 'Cryptocurrency sold');
            
            $this->recordTransaction($toUserId, $cryptoId, 'trade_buy', $amount, 
                                   $toWallet['balance'], $newToBalance, 
                                   $referenceType, $referenceId, 'Cryptocurrency purchased');
            
            $this->db->endTransaction();
            
            return ['success' => true, 'message' => 'Transfer completed successfully'];
            
        } catch (Exception $e) {
            $this->db->cancelTransaction();
            error_log('Transfer funds error: ' . $e->getMessage());
            return ['success' => false, 'message' => $e->getMessage()];
        }
    }
    
    // Transfer funds from escrow (used by Escrow class)
    public function transferFromEscrow($fromUserId, $toUserId, $cryptoId, $amount, $tradeId) {
        try {
            $this->db->beginTransaction();
            
            // Get sender wallet (locked balance will be reduced)
            $fromWallet = $this->getWallet($fromUserId, $cryptoId);
            if (!$fromWallet || $fromWallet['locked_balance'] < $amount) {
                throw new Exception('Insufficient locked balance in escrow');
            }
            
            // Get receiver wallet
            $toWallet = $this->getWallet($toUserId, $cryptoId);
            if (!$toWallet) {
                throw new Exception('Receiver wallet not found');
            }
            
            // Update sender wallet (reduce locked balance)
            $newFromLockedBalance = $fromWallet['locked_balance'] - $amount;
            $this->db->query("UPDATE wallets SET locked_balance = :locked_balance 
                             WHERE user_id = :user_id AND crypto_id = :crypto_id");
            $this->db->bind(':locked_balance', $newFromLockedBalance);
            $this->db->bind(':user_id', $fromUserId);
            $this->db->bind(':crypto_id', $cryptoId);
            
            if (!$this->db->execute()) {
                throw new Exception('Failed to update sender wallet');
            }
            
            // Update receiver wallet (increase available balance)
            $newToBalance = $toWallet['balance'] + $amount;
            $this->db->query("UPDATE wallets SET balance = :balance 
                             WHERE user_id = :user_id AND crypto_id = :crypto_id");
            $this->db->bind(':balance', $newToBalance);
            $this->db->bind(':user_id', $toUserId);
            $this->db->bind(':crypto_id', $cryptoId);
            
            if (!$this->db->execute()) {
                throw new Exception('Failed to update receiver wallet');
            }
            
            // Record transactions
            $this->recordTransaction($fromUserId, $cryptoId, 'escrow_release', -$amount, 
                                   $fromWallet['balance'], $fromWallet['balance'], 
                                   'trade', $tradeId, 'Funds released from escrow');
            
            $this->recordTransaction($toUserId, $cryptoId, 'escrow_receive', $amount, 
                                   $toWallet['balance'], $newToBalance, 
                                   'trade', $tradeId, 'Funds received from escrow');
            
            $this->db->endTransaction();
            
            return ['success' => true, 'message' => 'Escrow transfer completed successfully'];
            
        } catch (Exception $e) {
            $this->db->cancelTransaction();
            error_log('Escrow transfer error: ' . $e->getMessage());
            return ['success' => false, 'message' => $e->getMessage()];
        }
    }
    
    // Get wallet summary for dashboard
    public function getWalletSummary($userId) {
        $this->db->query("SELECT 
                             COUNT(*) as total_wallets,
                             COUNT(CASE WHEN balance > 0 THEN 1 END) as active_wallets,
                             SUM(balance * current_price) as total_value,
                             SUM(locked_balance * current_price) as locked_value
                         FROM wallets w 
                         JOIN cryptocurrencies c ON w.crypto_id = c.id 
                         WHERE w.user_id = :user_id AND c.is_active = 1");
        $this->db->bind(':user_id', $userId);
        return $this->db->single();
    }
    
    // Get top wallets by value
    public function getTopWallets($userId, $limit = 5) {
        $this->db->query("SELECT w.*, c.symbol, c.name, c.current_price,
                             (w.balance * c.current_price) as total_value
                         FROM wallets w 
                         JOIN cryptocurrencies c ON w.crypto_id = c.id 
                         WHERE w.user_id = :user_id AND c.is_active = 1 AND w.balance > 0
                         ORDER BY total_value DESC 
                         LIMIT :limit");
        $this->db->bind(':user_id', $userId);
        $this->db->bind(':limit', $limit);
        return $this->db->resultSet();
    }
    
    // Record transaction
    private function recordTransaction($userId, $cryptoId, $type, $amount, $balanceBefore, $balanceAfter, $referenceType = null, $referenceId = null, $notes = null) {
        $this->db->query("INSERT INTO transactions (user_id, crypto_id, transaction_type, amount, balance_before, balance_after, reference_type, reference_id, notes, status) 
                         VALUES (:user_id, :crypto_id, :type, :amount, :balance_before, :balance_after, :ref_type, :ref_id, :notes, 'confirmed')");
        
        $this->db->bind(':user_id', $userId);
        $this->db->bind(':crypto_id', $cryptoId);
        $this->db->bind(':type', $type);
        $this->db->bind(':amount', $amount);
        $this->db->bind(':balance_before', $balanceBefore);
        $this->db->bind(':balance_after', $balanceAfter);
        $this->db->bind(':ref_type', $referenceType);
        $this->db->bind(':ref_id', $referenceId);
        $this->db->bind(':notes', $notes);
        
        $this->db->execute();
    }
    
    // Get transaction history
    public function getTransactionHistory($userId, $limit = 50) {
        $this->db->query("SELECT t.*, c.symbol, c.name 
                         FROM transactions t 
                         JOIN cryptocurrencies c ON t.crypto_id = c.id 
                         WHERE t.user_id = :user_id 
                         ORDER BY t.created_at DESC 
                         LIMIT :limit");
        $this->db->bind(':user_id', $userId);
        $this->db->bind(':limit', $limit);
        return $this->db->resultSet();
    }
}
?>