<?php
/**
 * TokenSystem - Advanced Credit/Token Management System
 * Handles all token-based transactions and budget management
 */

class TokenSystem {
    private static $pdo = null;
    
    /**
     * Initialize the TokenSystem with database connection
     */
    public static function init($database_connection) {
        self::$pdo = $database_connection;
    }
    
    /**
     * Charge tokens for a specific action
     * 
     * @param string $action_name The name of the action to charge for
     * @param int $user_id The user performing the action
     * @param array $reference Optional reference data (event_id, participant_id, etc.)
     * @return array Result with success status and message
     */
    public static function charge($action_name, $user_id, $reference = []) {
        try {
            // Get action details
            $action = self::getAction($action_name);
            if (!$action) {
                return ['success' => false, 'message' => "Action '$action_name' not found"];
            }
            
            if (!$action['is_active']) {
                return ['success' => false, 'message' => "Action '$action_name' is not active"];
            }
            
            // Get user's group budget
            $budget = self::getUserBudget($user_id);
            if (!$budget) {
                return ['success' => false, 'message' => 'No budget found for user group'];
            }
            
            // Check if sufficient balance
            if ($budget['balance'] < $action['token_cost']) {
                return [
                    'success' => false, 
                    'message' => "Insufficient tokens. Required: {$action['token_cost']}, Available: {$budget['balance']}",
                    'required' => $action['token_cost'],
                    'available' => $budget['balance'],
                    'deficit' => $action['token_cost'] - $budget['balance']
                ];
            }
            
            // Process the charge
            $transaction_id = self::processTransaction(
                $budget['id'],
                $action['id'],
                $user_id,
                'debit',
                $action['token_cost'],
                $action['action_description'],
                $reference
            );
            
            if ($transaction_id) {
                return [
                    'success' => true,
                    'message' => "Successfully charged {$action['token_cost']} tokens for {$action_name}",
                    'transaction_id' => $transaction_id,
                    'charged_amount' => $action['token_cost'],
                    'new_balance' => $budget['balance'] - $action['token_cost']
                ];
            } else {
                return ['success' => false, 'message' => 'Failed to process transaction'];
            }
            
        } catch (Exception $e) {
            return ['success' => false, 'message' => 'System error: ' . $e->getMessage()];
        }
    }
    
    /**
     * Check if user has sufficient balance for an action
     */
    public static function canAfford($action_name, $user_id) {
        $action = self::getAction($action_name);
        if (!$action) return false;
        
        $budget = self::getUserBudget($user_id);
        if (!$budget) return false;
        
        return $budget['balance'] >= $action['token_cost'];
    }
    
    /**
     * Get user's current token balance
     */
    public static function getBalance($user_id) {
        $budget = self::getUserBudget($user_id);
        return $budget ? $budget['balance'] : 0;
    }
    
    /**
     * Add tokens to user's budget (purchase/refund)
     */
    public static function addTokens($user_id, $amount, $type = 'purchase', $description = '') {
        try {
            $budget = self::getUserBudget($user_id);
            if (!$budget) {
                return ['success' => false, 'message' => 'No budget found for user group'];
            }
            
            $transaction_id = self::processTransaction(
                $budget['id'],
                null,
                $user_id,
                $type,
                $amount,
                $description ?: "Token $type"
            );
            
            return [
                'success' => true,
                'message' => "Successfully added $amount tokens",
                'transaction_id' => $transaction_id,
                'new_balance' => $budget['balance'] + $amount
            ];
            
        } catch (Exception $e) {
            return ['success' => false, 'message' => 'System error: ' . $e->getMessage()];
        }
    }
    
    /**
     * Get transaction history for a user/group
     */
    public static function getTransactionHistory($user_id, $limit = 50) {
        $budget = self::getUserBudget($user_id);
        if (!$budget) return [];
        
        $stmt = self::$pdo->prepare("
            SELECT t.*, ta.action_name, ta.action_description, u.username
            FROM token_transactions t
            LEFT JOIN token_actions ta ON t.action_id = ta.id
            LEFT JOIN users u ON t.user_id = u.id
            WHERE t.budget_id = ?
            ORDER BY t.created_at DESC
            LIMIT ?
        ");
        $stmt->execute([$budget['id'], $limit]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    
    /**
     * Get all available actions with pricing
     */
    public static function getActions($category = null) {
        $sql = "SELECT * FROM token_actions WHERE is_active = 1";
        $params = [];
        
        if ($category) {
            $sql .= " AND category = ?";
            $params[] = $category;
        }
        
        $sql .= " ORDER BY category, action_name";
        
        $stmt = self::$pdo->prepare($sql);
        $stmt->execute($params);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    
    /**
     * Get action by name
     */
    private static function getAction($action_name) {
        $stmt = self::$pdo->prepare("SELECT * FROM token_actions WHERE action_name = ? AND is_active = 1");
        $stmt->execute([$action_name]);
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }
    
    /**
     * Get user's group budget
     */
    private static function getUserBudget($user_id) {
        $stmt = self::$pdo->prepare("
            SELECT b.* FROM budgets b
            JOIN user_group_memberships ugm ON b.group_id = ugm.group_id
            WHERE ugm.user_id = ?
            LIMIT 1
        ");
        $stmt->execute([$user_id]);
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }
    
    /**
     * Process a transaction
     */
    private static function processTransaction($budget_id, $action_id, $user_id, $type, $amount, $description, $reference = []) {
        self::$pdo->beginTransaction();
        
        try {
            // Get current balance
            $stmt = self::$pdo->prepare("SELECT balance FROM budgets WHERE id = ? FOR UPDATE");
            $stmt->execute([$budget_id]);
            $current_balance = $stmt->fetchColumn();
            
            // Calculate new balance
            $new_balance = $type === 'debit' ? $current_balance - $amount : $current_balance + $amount;
            
            // Update budget
            $stmt = self::$pdo->prepare("UPDATE budgets SET balance = ?, total_spent = total_spent + ?, updated_at = NOW() WHERE id = ?");
            $spend_amount = $type === 'debit' ? $amount : 0;
            $stmt->execute([$new_balance, $spend_amount, $budget_id]);
            
            // Insert transaction record
            $stmt = self::$pdo->prepare("
                INSERT INTO token_transactions 
                (budget_id, action_id, user_id, transaction_type, amount, balance_before, balance_after, description, reference_id, reference_type, ip_address, user_agent)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            ");
            
            $reference_id = $reference['id'] ?? ($reference['event_id'] ?? ($reference['participant_id'] ?? ($reference['judge_id'] ?? null)));
            $reference_type = $reference['type'] ?? ($reference['event_id'] ? 'event' : ($reference['participant_id'] ? 'participant' : ($reference['judge_id'] ? 'judge' : null)));
            
            $stmt->execute([
                $budget_id,
                $action_id,
                $user_id,
                $type,
                $amount,
                $current_balance,
                $new_balance,
                $description,
                $reference_id,
                $reference_type,
                $_SERVER['REMOTE_ADDR'] ?? null,
                $_SERVER['HTTP_USER_AGENT'] ?? null
            ]);
            
            $transaction_id = self::$pdo->lastInsertId();
            self::$pdo->commit();
            
            return $transaction_id;
            
        } catch (Exception $e) {
            self::$pdo->rollback();
            throw $e;
        }
    }
    
    /**
     * Generate usage widget HTML for embedding
     */
    public static function generateWidget($user_id) {
        $budget = self::getUserBudget($user_id);
        $balance = $budget ? $budget['balance'] : 0;
        
        return "
        <div class='token-widget' style='background: #f8f9fa; padding: 10px; border-radius: 8px; border-left: 4px solid #007bff; margin: 10px 0;'>
            <div style='display: flex; justify-content: space-between; align-items: center;'>
                <span style='font-weight: 600; color: #495057;'>
                    <i class='fas fa-coins' style='color: #ffc107; margin-right: 5px;'></i>Token Balance
                </span>
                <span style='font-size: 1.2em; font-weight: bold; color: " . ($balance > 10 ? '#28a745' : '#dc3545') . ";'>
                    {$balance}
                </span>
            </div>
            " . ($balance <= 10 ? "<small style='color: #dc3545; margin-top: 5px; display: block;'><i class='fas fa-exclamation-triangle'></i> Low balance! Consider purchasing more tokens.</small>" : "") . "
        </div>";
    }
    
    /**
     * Get usage statistics
     */
    public static function getUsageStats($user_id, $days = 30) {
        $budget = self::getUserBudget($user_id);
        if (!$budget) return [];
        
        $stmt = self::$pdo->prepare("
            SELECT 
                DATE(created_at) as date,
                SUM(CASE WHEN transaction_type = 'debit' THEN amount ELSE 0 END) as spent,
                SUM(CASE WHEN transaction_type IN ('credit', 'purchase') THEN amount ELSE 0 END) as added,
                COUNT(*) as transactions
            FROM token_transactions 
            WHERE budget_id = ? AND created_at >= DATE_SUB(NOW(), INTERVAL ? DAY)
            GROUP BY DATE(created_at)
            ORDER BY date DESC
        ");
        $stmt->execute([$budget['id'], $days]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
}

// Auto-initialize if database connection is available
if (isset($pdo)) {
    TokenSystem::init($pdo);
}
?>
