<?php
/**
 * Common functions for the application
 */

/**
 * Log login attempts to the database
 * 
 * @param PDO $db Database connection
 * @param string $username Username that attempted to log in
 * @param bool $success Whether the login was successful
 * @param int|null $user_id User ID if login was successful
 * @return bool Success of logging the attempt
 */
function logLoginAttempt($db, $username, $success, $user_id = null) {
    try {
        // Check if the table exists
        $stmt = $db->prepare("SHOW TABLES LIKE 'login_attempts'");
        $stmt->execute();
        if ($stmt->rowCount() == 0) {
            // Table doesn't exist, just return without logging
            error_log("Warning: login_attempts table doesn't exist");
            return false;
        }
        
        // Check if the username column exists
        $stmt = $db->prepare("SHOW COLUMNS FROM login_attempts LIKE 'username'");
        $stmt->execute();
        if ($stmt->rowCount() == 0) {
            // Column doesn't exist, log without username
            error_log("Warning: username column doesn't exist in login_attempts table");
            $stmt = $db->prepare("INSERT INTO login_attempts (success, user_id, ip_address, attempt_time) 
                                 VALUES (?, ?, ?, NOW())");
            $stmt->execute([
                $success ? 1 : 0,
                $user_id,
                $_SERVER['REMOTE_ADDR']
            ]);
        } else {
            // Normal case - all columns exist
            $stmt = $db->prepare("INSERT INTO login_attempts (username, success, user_id, ip_address, attempt_time) 
                                 VALUES (?, ?, ?, ?, NOW())");
            $stmt->execute([
                $username,
                $success ? 1 : 0,
                $user_id,
                $_SERVER['REMOTE_ADDR']
            ]);
        }
        return true;
    } catch (Exception $e) {
        error_log("Error logging login attempt: " . $e->getMessage());
        return false;
    }
}

/**
 * Generate a CSRF token and store it in the session
 * 
 * @return string The generated CSRF token
 */
function generateCSRFToken() {
    $token = bin2hex(random_bytes(32));
    $_SESSION['csrf_token'] = $token;
    return $token;
}

/**
 * Validate a CSRF token against the one stored in the session
 * 
 * @param string $token The token to validate
 * @return bool Whether the token is valid
 */
function validateCSRFToken($token) {
    return isset($_SESSION['csrf_token']) && $token === $_SESSION['csrf_token'];
}

/**
 * Format currency amount with proper symbol
 * 
 * @param float $amount The amount to format
 * @param string $currency The currency code (USD, EUR, etc.)
 * @return string Formatted currency string
 */
function formatCurrency($amount, $currency = 'USD') {
    $symbols = [
        'USD' => '$',
        'EUR' => '€',
        'GBP' => '£',
        'JPY' => '¥',
        'AUD' => 'A$',
        'CAD' => 'C$',
        'CHF' => 'CHF',
        'CNY' => '¥',
        'INR' => '₹',
    ];
    
    $symbol = $symbols[$currency] ?? $currency . ' ';
    
    switch ($currency) {
        case 'JPY':
        case 'CNY':
            return $symbol . number_format($amount, 0);
        default:
            return $symbol . number_format($amount, 2);
    }
}

/**
 * Get user data by ID
 * 
 * @param PDO $db Database connection
 * @param int $userId User ID
 * @return array|false User data or false if not found
 */
function getUserById($db, $userId) {
    try {
        $stmt = $db->prepare("SELECT * FROM users WHERE id = ?");
        $stmt->execute([$userId]);
        return $stmt->fetch(PDO::FETCH_ASSOC);
    } catch (Exception $e) {
        error_log("Error fetching user: " . $e->getMessage());
        return false;
    }
}

/**
 * Get account balance for a user
 * 
 * @param PDO $db Database connection
 * @param int $userId User ID
 * @param string $currency Currency code (optional)
 * @return array|float Account balance(s)
 */
function getAccountBalance($db, $userId, $currency = null) {
    try {
        if ($currency) {
            $stmt = $db->prepare("SELECT balance FROM account_balances WHERE user_id = ? AND currency = ?");
            $stmt->execute([$userId, $currency]);
            $result = $stmt->fetch(PDO::FETCH_ASSOC);
            return $result ? (float)$result['balance'] : 0.00;
        } else {
            $stmt = $db->prepare("SELECT currency, balance FROM account_balances WHERE user_id = ?");
            $stmt->execute([$userId]);
            $balances = [];
            while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
                $balances[$row['currency']] = (float)$row['balance'];
            }
            return $balances;
        }
    } catch (Exception $e) {
        error_log("Error fetching balance: " . $e->getMessage());
        return $currency ? 0.00 : [];
    }
}

/**
 * Get recent transactions for a user
 * 
 * @param PDO $db Database connection
 * @param int $userId User ID
 * @param int $limit Number of transactions to return
 * @return array List of transactions
 */
function getRecentTransactions($db, $userId, $limit = 10) {
    try {
        $stmt = $db->prepare("
            SELECT * FROM transactions 
            WHERE user_id = ? OR recipient_id = ? 
            ORDER BY transaction_date DESC 
            LIMIT ?
        ");
        $stmt->execute([$userId, $userId, $limit]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    } catch (Exception $e) {
        error_log("Error fetching transactions: " . $e->getMessage());
        return [];
    }
}

/**
 * Check if user has sufficient balance for a transaction
 * 
 * @param PDO $db Database connection
 * @param int $userId User ID
 * @param float $amount Transaction amount
 * @param string $currency Currency code
 * @return bool Whether user has sufficient balance
 */
function hasSufficientBalance($db, $userId, $amount, $currency) {
    $balance = getAccountBalance($db, $userId, $currency);
    return $balance >= $amount;
}

/**
 * Create a new transaction
 * 
 * @param PDO $db Database connection
 * @param array $transactionData Transaction details
 * @return int|false Transaction ID or false on failure
 */
function createTransaction($db, $transactionData) {
    try {
        $db->beginTransaction();
        
        // Insert transaction record
        $stmt = $db->prepare("
            INSERT INTO transactions (
                user_id, recipient_id, amount, currency, 
                transaction_type, status, description, reference_number, 
                transaction_date
            ) VALUES (
                :userId, :recipientId, :amount, :currency,
                :type, :status, :description, :reference, 
                NOW()
            )
        ");
        
        $stmt->execute([
            ':userId' => $transactionData['user_id'],
            ':recipientId' => $transactionData['recipient_id'] ?? null,
            ':amount' => $transactionData['amount'],
            ':currency' => $transactionData['currency'],
            ':type' => $transactionData['type'],
            ':status' => $transactionData['status'] ?? 'completed',
            ':description' => $transactionData['description'] ?? '',
            ':reference' => $transactionData['reference'] ?? generateReferenceNumber()
        ]);
        
        $transactionId = $db->lastInsertId();
        
        // Update sender's balance
        if ($transactionData['type'] != 'deposit') {
            $stmt = $db->prepare("
                UPDATE account_balances 
                SET balance = balance - :amount, 
                    last_updated = NOW() 
                WHERE user_id = :userId AND currency = :currency
            ");
            $stmt->execute([
                ':amount' => $transactionData['amount'],
                ':userId' => $transactionData['user_id'],
                ':currency' => $transactionData['currency']
            ]);
        }
        
        // Update recipient's balance for transfers
        if ($transactionData['type'] == 'transfer' && isset($transactionData['recipient_id'])) {
            $stmt = $db->prepare("
                UPDATE account_balances 
                SET balance = balance + :amount, 
                    last_updated = NOW() 
                WHERE user_id = :recipientId AND currency = :currency
            ");
            $stmt->execute([
                ':amount' => $transactionData['amount'],
                ':recipientId' => $transactionData['recipient_id'],
                ':currency' => $transactionData['currency']
            ]);
        }
        
        $db->commit();
        return $transactionId;
    } catch (Exception $e) {
        $db->rollBack();
        error_log("Transaction error: " . $e->getMessage());
        return false;
    }
}

/**
 * Generate a unique reference number for transactions
 * 
 * @return string Reference number
 */
function generateReferenceNumber() {
    return 'TXN' . strtoupper(substr(uniqid() . bin2hex(random_bytes(4)), 0, 12));
}

/**
 * Sanitize user input
 * 
 * @param string $input Input to sanitize
 * @return string Sanitized input
 */
function sanitizeInput($input) {
    return htmlspecialchars(trim($input), ENT_QUOTES, 'UTF-8');
}

/**
 * Check if a user session is active
 * 
 * @return bool Whether user is logged in
 */
function isLoggedIn() {
    return isset($_SESSION['user_id']);
}

/**
 * Redirect to login page if user is not logged in
 * 
 * @param string $redirect URL to redirect to after login
 * @return void
 */
function requireLogin($redirect = null) {
    if (!isLoggedIn()) {
        if ($redirect) {
            $_SESSION['redirect_after_login'] = $redirect;
        }
        header('Location: login.php');
        exit;
    }
}

/**
 * Log user activity
 * 
 * @param PDO $db Database connection
 * @param int $userId User ID
 * @param string $action Action performed
 * @param string $details Additional details
 * @return bool Success of logging the activity
 */
function logUserActivity($db, $userId, $action, $details = '') {
    try {
        $stmt = $db->prepare("
            INSERT INTO user_activity_logs (
                user_id, action, details, ip_address, user_agent, created_at
            ) VALUES (
                ?, ?, ?, ?, ?, NOW()
            )
        ");
        $stmt->execute([
            $userId,
            $action,
            $details,
            $_SERVER['REMOTE_ADDR'],
            $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown'
        ]);
        return true;
    } catch (Exception $e) {
        error_log("Error logging user activity: " . $e->getMessage());
        return false;
    }
}

/**
 * Send email notification
 * 
 * @param string $to Recipient email
 * @param string $subject Email subject
 * @param string $message Email body
 * @param array $attachments Optional attachments
 * @return bool Whether email was sent successfully
 */
function sendEmail($to, $subject, $message, $attachments = []) {
    // This is a placeholder. Implement with your preferred email library
    // such as PHPMailer, Swift Mailer, or mail()
    
    // For now, just log that we would send an email
    error_log("Would send email to $to with subject: $subject");
    return true;
}
?>
