<?php
/**
 * API Key Manager Class
 * Handles API key generation, validation, and management
 */

class ApiKeyManager {
    private $conn;
    
    public function __construct($connection) {
        $this->conn = $connection;
    }
    
    /**
     * Generate a new API key and secret
     */
    public function generateApiKey($userId, $name, $description = '', $permissions = null, $rateLimit = 1000, $expiresAt = null) {
        // Generate API key (32 characters)
        $apiKey = $this->generateRandomString(32);
        
        // Generate API secret (64 characters)
        $apiSecret = $this->generateRandomString(64);
        
        // Hash the secret for storage
        $hashedSecret = hash('sha256', $apiSecret);
        
        // Insert into database
        $stmt = $this->conn->prepare("
            INSERT INTO api_keys (user_id, api_key, api_secret, name, description, permissions, rate_limit, expires_at) 
            VALUES (?, ?, ?, ?, ?, ?, ?, ?)
        ");
        
        $permissionsJson = $permissions ? json_encode($permissions) : null;
        $stmt->bind_param("isssssis", $userId, $apiKey, $hashedSecret, $name, $description, $permissionsJson, $rateLimit, $expiresAt);
        
        if ($stmt->execute()) {
            $keyId = $this->conn->insert_id;
            $stmt->close();
            
            return [
                'success' => true,
                'key_id' => $keyId,
                'api_key' => $apiKey,
                'api_secret' => $apiSecret, // Return unhashed secret only once
                'message' => 'API key generated successfully'
            ];
        } else {
            $stmt->close();
            return [
                'success' => false,
                'message' => 'Failed to generate API key: ' . $this->conn->error
            ];
        }
    }
    
    /**
     * Validate API key and secret
     */
    public function validateApiKey($apiKey, $apiSecret = null) {
        $stmt = $this->conn->prepare("
            SELECT ak.*, a.username, a.role, a.balance, a.api_key_enabled 
            FROM api_keys ak 
            JOIN agents a ON ak.user_id = a.id 
            WHERE ak.api_key = ? AND ak.is_active = 1 
            AND (ak.expires_at IS NULL OR ak.expires_at > NOW())
        ");
        
        $stmt->bind_param("s", $apiKey);
        $stmt->execute();
        $result = $stmt->get_result();
        
        if ($result->num_rows === 0) {
            $stmt->close();
            return [
                'valid' => false,
                'message' => 'Invalid or expired API key'
            ];
        }
        
        $keyData = $result->fetch_assoc();
        $stmt->close();
        
        // Check if user has API access enabled
        if (!$keyData['api_key_enabled']) {
            return [
                'valid' => false,
                'message' => 'API access is disabled for this user'
            ];
        }
        
        // If secret is provided, validate it
        if ($apiSecret !== null) {
            $hashedSecret = hash('sha256', $apiSecret);
            if (!hash_equals($keyData['api_secret'], $hashedSecret)) {
                return [
                    'valid' => false,
                    'message' => 'Invalid API secret'
                ];
            }
        }
        
        // Update usage statistics
        $this->updateUsageStats($keyData['id'], $keyData['user_id']);
        
        return [
            'valid' => true,
            'user_id' => $keyData['user_id'],
            'username' => $keyData['username'],
            'role' => $keyData['role'],
            'balance' => $keyData['balance'],
            'permissions' => $keyData['permissions'] ? json_decode($keyData['permissions'], true) : null,
            'rate_limit' => $keyData['rate_limit'],
            'key_data' => $keyData
        ];
    }
    
    /**
     * Get user's API keys
     */
    public function getUserApiKeys($userId) {
        $stmt = $this->conn->prepare("
            SELECT id, api_key, name, description, permissions, is_active, 
                   last_used, usage_count, rate_limit, expires_at, created_at
            FROM api_keys 
            WHERE user_id = ? 
            ORDER BY created_at DESC
        ");
        
        $stmt->bind_param("i", $userId);
        $stmt->execute();
        $result = $stmt->get_result();
        
        $keys = [];
        while ($row = $result->fetch_assoc()) {
            $row['permissions'] = $row['permissions'] ? json_decode($row['permissions'], true) : null;
            $row['api_key_masked'] = $this->maskApiKey($row['api_key']);
            $keys[] = $row;
        }
        
        $stmt->close();
        return $keys;
    }
    
    /**
     * Get all API keys (admin function)
     */
    public function getAllApiKeys($limit = 100, $offset = 0) {
        $stmt = $this->conn->prepare("
            SELECT ak.*, a.username, a.role, a.email
            FROM api_keys ak 
            JOIN agents a ON ak.user_id = a.id 
            ORDER BY ak.created_at DESC 
            LIMIT ? OFFSET ?
        ");
        
        $stmt->bind_param("ii", $limit, $offset);
        $stmt->execute();
        $result = $stmt->get_result();
        
        $keys = [];
        while ($row = $result->fetch_assoc()) {
            $row['permissions'] = $row['permissions'] ? json_decode($row['permissions'], true) : null;
            $row['api_key_masked'] = $this->maskApiKey($row['api_key']);
            $keys[] = $row;
        }
        
        $stmt->close();
        return $keys;
    }
    
    /**
     * Update API key
     */
    public function updateApiKey($keyId, $name, $description, $permissions, $rateLimit, $isActive, $expiresAt) {
        $stmt = $this->conn->prepare("
            UPDATE api_keys 
            SET name = ?, description = ?, permissions = ?, rate_limit = ?, 
                is_active = ?, expires_at = ?, updated_at = NOW()
            WHERE id = ?
        ");
        
        $permissionsJson = $permissions ? json_encode($permissions) : null;
        $stmt->bind_param("sssiisi", $name, $description, $permissionsJson, $rateLimit, $isActive, $expiresAt, $keyId);
        
        $success = $stmt->execute();
        $stmt->close();
        
        return $success;
    }
    
    /**
     * Delete API key
     */
    public function deleteApiKey($keyId, $userId = null) {
        $sql = "DELETE FROM api_keys WHERE id = ?";
        $params = [$keyId];
        $types = "i";
        
        if ($userId !== null) {
            $sql .= " AND user_id = ?";
            $params[] = $userId;
            $types .= "i";
        }
        
        $stmt = $this->conn->prepare($sql);
        $stmt->bind_param($types, ...$params);
        $success = $stmt->execute();
        $stmt->close();
        
        return $success;
    }
    
    /**
     * Check rate limit
     */
    public function checkRateLimit($apiKeyId, $endpoint) {
        // Get current rate limit for this key
        $stmt = $this->conn->prepare("SELECT rate_limit FROM api_keys WHERE id = ?");
        $stmt->bind_param("i", $apiKeyId);
        $stmt->execute();
        $result = $stmt->get_result();
        $keyData = $result->fetch_assoc();
        $stmt->close();
        
        if (!$keyData) {
            return ['allowed' => false, 'message' => 'Invalid API key'];
        }
        
        $rateLimit = $keyData['rate_limit'];
        $windowStart = date('Y-m-d H:00:00'); // Current hour
        $windowEnd = date('Y-m-d H:59:59');
        
        // Get current usage for this hour
        $stmt = $this->conn->prepare("
            SELECT COUNT(*) as usage_count 
            FROM api_usage_logs 
            WHERE api_key_id = ? AND endpoint = ? 
            AND created_at BETWEEN ? AND ?
        ");
        $stmt->bind_param("isss", $apiKeyId, $endpoint, $windowStart, $windowEnd);
        $stmt->execute();
        $result = $stmt->get_result();
        $usage = $result->fetch_assoc();
        $stmt->close();
        
        $currentUsage = $usage['usage_count'];
        
        if ($currentUsage >= $rateLimit) {
            return [
                'allowed' => false, 
                'message' => 'Rate limit exceeded',
                'current_usage' => $currentUsage,
                'rate_limit' => $rateLimit
            ];
        }
        
        return [
            'allowed' => true,
            'current_usage' => $currentUsage,
            'rate_limit' => $rateLimit,
            'remaining' => $rateLimit - $currentUsage
        ];
    }
    
    /**
     * Log API usage
     */
    public function logApiUsage($apiKeyId, $userId, $endpoint, $method, $ipAddress, $userAgent, $requestData, $responseStatus, $responseTime) {
        $stmt = $this->conn->prepare("
            INSERT INTO api_usage_logs 
            (api_key_id, user_id, endpoint, method, ip_address, user_agent, request_data, response_status, response_time)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
        ");
        
        $requestDataJson = $requestData ? json_encode($requestData) : null;
        $stmt->bind_param("iisssssii", $apiKeyId, $userId, $endpoint, $method, $ipAddress, $userAgent, $requestDataJson, $responseStatus, $responseTime);
        $stmt->execute();
        $stmt->close();
    }
    
    /**
     * Update usage statistics
     */
    private function updateUsageStats($keyId, $userId) {
        $stmt = $this->conn->prepare("
            UPDATE api_keys 
            SET last_used = NOW(), usage_count = usage_count + 1 
            WHERE id = ?
        ");
        $stmt->bind_param("i", $keyId);
        $stmt->execute();
        $stmt->close();
    }
    
    /**
     * Generate random string
     */
    private function generateRandomString($length) {
        $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $charactersLength = strlen($characters);
        $randomString = '';
        
        for ($i = 0; $i < $length; $i++) {
            $randomString .= $characters[rand(0, $charactersLength - 1)];
        }
        
        return $randomString;
    }
    
    /**
     * Mask API key for display
     */
    private function maskApiKey($apiKey) {
        if (strlen($apiKey) <= 8) {
            return str_repeat('*', strlen($apiKey));
        }
        
        return substr($apiKey, 0, 4) . str_repeat('*', strlen($apiKey) - 8) . substr($apiKey, -4);
    }
    
    /**
     * Enable/disable API access for user
     */
    public function setUserApiAccess($userId, $enabled) {
        $stmt = $this->conn->prepare("UPDATE agents SET api_key_enabled = ? WHERE id = ?");
        $stmt->bind_param("ii", $enabled, $userId);
        $success = $stmt->execute();
        $stmt->close();
        
        return $success;
    }
    
    /**
     * Get API usage statistics
     */
    public function getApiUsageStats($userId = null, $days = 30) {
        $sql = "
            SELECT 
                DATE(created_at) as date,
                COUNT(*) as total_requests,
                COUNT(CASE WHEN response_status >= 200 AND response_status < 300 THEN 1 END) as successful_requests,
                COUNT(CASE WHEN response_status >= 400 THEN 1 END) as failed_requests,
                AVG(response_time) as avg_response_time
            FROM api_usage_logs 
            WHERE created_at >= DATE_SUB(NOW(), INTERVAL ? DAY)
        ";
        
        $params = [$days];
        $types = "i";
        
        if ($userId !== null) {
            $sql .= " AND user_id = ?";
            $params[] = $userId;
            $types .= "i";
        }
        
        $sql .= " GROUP BY DATE(created_at) ORDER BY date DESC";
        
        $stmt = $this->conn->prepare($sql);
        $stmt->bind_param($types, ...$params);
        $stmt->execute();
        $result = $stmt->get_result();
        
        $stats = [];
        while ($row = $result->fetch_assoc()) {
            $stats[] = $row;
        }
        
        $stmt->close();
        return $stats;
    }
}
?>


