<?php
/**
 * API Authentication Middleware
 * Handles both session-based and API key-based authentication
 */

require_once __DIR__ . '/ApiKeyManager.php';
require_once __DIR__ . '/network.php';

class ApiAuth {
    private $apiKeyManager;
    private $netInfo;
    
    public function __construct() {
        $this->apiKeyManager = new ApiKeyManager();
        $this->netInfo = new network_info();
    }
    
    /**
     * Authenticate API request using either session or API key
     */
    public function authenticate() {
        // Try API key authentication first
        $apiAuth = $this->authenticateWithApiKey();
        if ($apiAuth['success']) {
            return $apiAuth;
        }
        
        // Fall back to session authentication for existing API endpoints
        $sessionAuth = $this->authenticateWithSession();
        if ($sessionAuth['success']) {
            return $sessionAuth;
        }
        
        return ['success' => false, 'error' => 'Authentication required'];
    }
    
    /**
     * Authenticate with API key
     */
    private function authenticateWithApiKey() {
        $headers = getallheaders();
        $apiKey = null;
        $apiSecret = null;
        
        // Check for API key in headers (case-insensitive)
        foreach ($headers as $headerName => $headerValue) {
            if (strcasecmp($headerName, 'X-API-Key') === 0) {
                $apiKey = $headerValue;
            }
            if (strcasecmp($headerName, 'X-API-Secret') === 0) {
                $apiSecret = $headerValue;
            }
        }
        
        // Fallback to $_SERVER variables if not found in getallheaders
        if (!$apiKey && isset($_SERVER['HTTP_X_API_KEY'])) {
            $apiKey = $_SERVER['HTTP_X_API_KEY'];
        }
        if (!$apiSecret && isset($_SERVER['HTTP_X_API_SECRET'])) {
            $apiSecret = $_SERVER['HTTP_X_API_SECRET'];
        }
        
        // Check for API key in Authorization header (Bearer format)
        if (!$apiKey && isset($headers['Authorization'])) {
            $authHeader = $headers['Authorization'];
            if (preg_match('/Bearer\s+(.+):(.+)/', $authHeader, $matches)) {
                $apiKey = $matches[1];
                $apiSecret = $matches[2];
            }
        }
        
        // Check for API key in query parameters (less secure, but supported)
        if (!$apiKey && isset($_GET['api_key']) && isset($_GET['api_secret'])) {
            $apiKey = $_GET['api_key'];
            $apiSecret = $_GET['api_secret'];
        }
        
        if (!$apiKey || !$apiSecret) {
            return ['success' => false, 'error' => 'API key not provided'];
        }
        
        $ipAddress = $this->netInfo->get_client_ip();
        $validation = $this->apiKeyManager->validateApiKey($apiKey, $apiSecret, $ipAddress);
        
        if ($validation['success']) {
            // Log the API usage
            $endpoint = $_SERVER['REQUEST_URI'];
            $method = $_SERVER['REQUEST_METHOD'];
            $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
            $responseTime = null; // Will be set by the calling code
            
            $this->apiKeyManager->logApiUsage(
                $validation['key_id'],
                $endpoint,
                $method,
                $ipAddress,
                200, // Success response code
                $responseTime,
                null, // Request data will be logged separately if needed
                $userAgent
            );
            
            return [
                'success' => true,
                'auth_type' => 'api_key',
                'key_id' => $validation['key_id'],
                'permissions' => $validation['permissions'],
                'created_by' => $validation['created_by']
            ];
        }
        
        return $validation;
    }
    
    /**
     * Authenticate with session (existing system)
     */
    private function authenticateWithSession() {
        if (!defined('AUTH_USER')) {
            return ['success' => false, 'error' => 'Session authentication required'];
        }
        
        return [
            'success' => true,
            'auth_type' => 'session',
            'username' => AUTH_USER,
            'is_root' => AUTH_USER === 'root'
        ];
    }
    
    /**
     * Check if authenticated user has specific permission
     */
    public function hasPermission($authData, $permission) {
        if ($authData['auth_type'] === 'api_key') {
            return isset($authData['permissions'][$permission]) && 
                   $authData['permissions'][$permission] === true;
        } else if ($authData['auth_type'] === 'session') {
            // For session auth, use existing permission system
            if ($authData['username'] === 'root') {
                return true; // Root has all permissions
            }
            
            // For non-root users, check specific permissions
            // This can be extended based on your permission system
            require_once __DIR__ . '/permission_manager.php';
            $permManager = new permission_manager();
            return $permManager->check_api_permission($authData['username'], $permission);
        }
        
        return false;
    }
    
    /**
     * Send JSON error response
     */
    public function sendError($message, $code = 400) {
        http_response_code($code);
        echo json_encode([
            'status' => 'error',
            'message' => $message,
            'timestamp' => date('c')
        ]);
        exit;
    }
    
    /**
     * Send JSON success response
     */
    public function sendSuccess($data = null, $message = null) {
        $response = [
            'status' => 'success',
            'timestamp' => date('c')
        ];
        
        if ($message) {
            $response['message'] = $message;
        }
        
        if ($data !== null) {
            $response['data'] = $data;
        }
        
        echo json_encode($response);
    }
    
    /**
     * Check rate limiting for API key
     */
    public function checkRateLimit($keyId) {
        // Rate limiting is handled in ApiKeyManager::validateApiKey
        // This method can be used for additional rate limiting if needed
        return true;
    }
}

/**
 * Helper function for API endpoints to authenticate and check permissions
 */
function api_authenticate($required_permission = null) {
    $auth = new ApiAuth();
    $authData = $auth->authenticate();
    
    if (!$authData['success']) {
        $auth->sendError($authData['error'], 401);
    }
    
    // Check specific permission if required
    if ($required_permission && !$auth->hasPermission($authData, $required_permission)) {
        $auth->sendError('Insufficient permissions', 403);
    }
    
    return $authData;
}

/**
 * Helper function to send API responses
 */
function api_response($success, $data = null, $message = null, $code = 200) {
    http_response_code($code);
    
    $response = [
        'status' => $success ? 'success' : 'error',
        'timestamp' => date('c')
    ];
    
    if ($message) {
        $response['message'] = $message;
    }
    
    if ($data !== null) {
        $response['data'] = $data;
    }
    
    echo json_encode($response);
    exit;
}
?>