<?php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');

// Handle preflight OPTIONS request
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit;
}

// Database configuration
$host = 'localhost:3306';
$dbname = 'gqdcvggs_traffic';
$username = 'gqdcvggs';
$password = 'imaors_management.346980*#@-onlyforcpanel;forchange';

// Environment variables from .env file - fallback to hardcoded values
if (file_exists('.env')) {
    $env = parse_ini_file('.env');
    $mapbox_token = $env['MAPBOX_API_KEY'] ?? '';
}

try {
    $pdo = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    sendResponse(['success' => false, 'message' => 'Database connection failed'], 500);
    exit;
}

// Parse request
$request_uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$path = trim(str_replace('/api', '', $request_uri), '/');
$method = $_SERVER['REQUEST_METHOD'];
$action = $_GET['action'] ?? '';

// Extract API key if provided
$api_key = $_GET['api_key'] ?? '';

// Get JWT token from Authorization header for authenticated routes
$token = null;
$user_id = null;
if (isset($_SERVER['HTTP_AUTHORIZATION'])) {
    if (preg_match('/Bearer\s(\S+)/', $_SERVER['HTTP_AUTHORIZATION'], $matches)) {
        $token = $matches[1];
        // If we have a token, verify it and extract user ID
        if ($token) {
            try {
                $user = verifyJWTToken($token);
                if ($user) {
                    $user_id = $user['id'];
                }
            } catch (Exception $e) {
                // Invalid token, will continue as unauthenticated
            }
        }
    }
}

// Process the request
if ($action) {
    // Legacy API format with action parameter
    processLegacyRequest($pdo, $action, $api_key, $user_id);
} else {
    // RESTful API format with path-based routing
    processRESTRequest($pdo, $path, $method, $api_key, $user_id);
}

// Process legacy API requests (for backward compatibility)
function processLegacyRequest($pdo, $action, $api_key, $user_id) {
    // Validate API key for certain actions
    $publicActions = ['getTrafficLights', 'getLightById'];
    if (!in_array($action, $publicActions) && !validateApiKey($pdo, $api_key) && !$user_id) {
        sendResponse(['success' => false, 'message' => 'Authentication required'], 401);
        return;
    }

    switch ($action) {
        case 'getTrafficLights':
            getAllLights($pdo);
            break;
        case 'getLightById':
            $id = isset($_GET['id']) ? $_GET['id'] : null;
            getLightById($pdo, $id);
            break;
        case 'addTrafficLight':
            addLight($pdo, $user_id);
            break;
        case 'updateTiming':
            updateLightTiming($pdo, $user_id);
            break;
        case 'getNearbylights':
            $lat = isset($_GET['lat']) ? $_GET['lat'] : null;
            $lng = isset($_GET['lng']) ? $_GET['lng'] : null;
            $radius = isset($_GET['radius']) ? $_GET['radius'] : 1;
            getNearbyLights($pdo, $lat, $lng, $radius);
            break;
        default:
            sendResponse(['success' => false, 'message' => 'Invalid action'], 404);
            break;
    }
}

// Process RESTful API requests
function processRESTRequest($pdo, $path, $method, $api_key, $user_id) {
    // Parse path segments
    $segments = explode('/', $path);
    $base = $segments[0] ?? '';

    // Route the request
    switch ($base) {
        case 'traffic-lights':
            handleTrafficLightsRoutes($pdo, $segments, $method, $user_id);
            break;
        case 'user':
            if (!$user_id) {
                sendResponse(['success' => false, 'message' => 'Authentication required'], 401);
                return;
            }
            handleUserRoutes($pdo, $segments, $method, $user_id);
            break;
        case 'login':
            if ($method === 'POST') {
                handleLogin($pdo);
            } else {
                sendResponse(['success' => false, 'message' => 'Method not allowed'], 405);
            }
            break;
        case 'register':
            if ($method === 'POST') {
                handleRegister($pdo);
            } else {
                sendResponse(['success' => false, 'message' => 'Method not allowed'], 405);
            }
            break;
        case 'mapbox-token':
            if ($method === 'GET') {
                global $mapbox_token;
                sendResponse(['success' => true, 'token' => $mapbox_token]);
            } else {
                sendResponse(['success' => false, 'message' => 'Method not allowed'], 405);
            }
            break;
        default:
            sendResponse(['success' => false, 'message' => 'Endpoint not found'], 404);
            break;
    }
}

// Traffic Lights routes handler
function handleTrafficLightsRoutes($pdo, $segments, $method, $user_id) {
    $id = $segments[1] ?? null;
    $action = $segments[2] ?? null;

    if (!$id) {
        // Collection endpoints: /traffic-lights
        switch ($method) {
            case 'GET':
                getAllLights($pdo);
                break;
            case 'POST':
                addLight($pdo, $user_id);
                break;
            default:
                sendResponse(['success' => false, 'message' => 'Method not allowed'], 405);
                break;
        }
    } else {
        // Resource endpoints: /traffic-lights/{id}
        if (!$action) {
            switch ($method) {
                case 'GET':
                    getLightById($pdo, $id);
                    break;
                case 'PUT':
                    updateLight($pdo, $id, $user_id);
                    break;
                case 'DELETE':
                    deleteLight($pdo, $id, $user_id);
                    break;
                default:
                    sendResponse(['success' => false, 'message' => 'Method not allowed'], 405);
                    break;
            }
        } else {
            // Sub-resource endpoints: /traffic-lights/{id}/{action}
            if ($action === 'timing' && $method === 'POST') {
                updateLightTiming($pdo, $user_id, $id);
            } else {
                sendResponse(['success' => false, 'message' => 'Endpoint not found'], 404);
            }
        }
    }
}

// User routes handler
function handleUserRoutes($pdo, $segments, $method, $user_id) {
    $resource = $segments[1] ?? null;

    if ($resource === 'traffic-lights') {
        if ($method === 'GET') {
            getUserTrafficLights($pdo, $user_id);
        } else {
            sendResponse(['success' => false, 'message' => 'Method not allowed'], 405);
        }
    } else if ($resource === 'profile') {
        switch ($method) {
            case 'GET':
                getUserProfile($pdo, $user_id);
                break;
            case 'PUT':
                updateUserProfile($pdo, $user_id);
                break;
            default:
                sendResponse(['success' => false, 'message' => 'Method not allowed'], 405);
                break;
        }
    } else {
        sendResponse(['success' => false, 'message' => 'Endpoint not found'], 404);
    }
}

// User login handler
function handleLogin($pdo) {
    $json = file_get_contents('php://input');
    $data = json_decode($json, true);
    
    if (!$data || !isset($data['email']) || !isset($data['password'])) {
        sendResponse(['success' => false, 'message' => 'Email and password are required'], 400);
        return;
    }
    
    try {
        $stmt = $pdo->prepare("SELECT id, name, email, password FROM users WHERE email = ?");
        $stmt->execute([$data['email']]);
        $user = $stmt->fetch(PDO::FETCH_ASSOC);
        
        if (!$user || !password_verify($data['password'], $user['password'])) {
            sendResponse(['success' => false, 'message' => 'Invalid email or password'], 401);
            return;
        }
        
        // Generate JWT token
        $token = generateJWTToken([
            'id' => $user['id'],
            'name' => $user['name'],
            'email' => $user['email']
        ]);
        
        sendResponse([
            'success' => true, 
            'message' => 'Login successful',
            'token' => $token,
            'user' => [
                'id' => $user['id'],
                'name' => $user['name'],
                'email' => $user['email']
            ]
        ]);
    } catch (PDOException $e) {
        sendResponse(['success' => false, 'message' => 'Login failed'], 500);
    }
}

// User registration handler
function handleRegister($pdo) {
    $json = file_get_contents('php://input');
    $data = json_decode($json, true);
    
    if (!$data || !isset($data['name']) || !isset($data['email']) || !isset($data['password'])) {
        sendResponse(['success' => false, 'message' => 'Name, email and password are required'], 400);
        return;
    }
    
    try {
        // Check if email already exists
        $stmt = $pdo->prepare("SELECT id FROM users WHERE email = ?");
        $stmt->execute([$data['email']]);
        if ($stmt->rowCount() > 0) {
            sendResponse(['success' => false, 'message' => 'Email already registered'], 409);
            return;
        }
        
        // Hash password
        $hashedPassword = password_hash($data['password'], PASSWORD_DEFAULT);
        
        // Insert new user
        $stmt = $pdo->prepare("INSERT INTO users (name, email, password, created_at) VALUES (?, ?, ?, NOW())");
        $stmt->execute([$data['name'], $data['email'], $hashedPassword]);
        
        $userId = $pdo->lastInsertId();
        
        // Generate JWT token
        $token = generateJWTToken([
            'id' => $userId,
            'name' => $data['name'],
            'email' => $data['email']
        ]);
        
        sendResponse([
            'success' => true, 
            'message' => 'Registration successful',
            'token' => $token,
            'user' => [
                'id' => $userId,
                'name' => $data['name'],
                'email' => $data['email']
            ]
        ]);
    } catch (PDOException $e) {
        sendResponse(['success' => false, 'message' => 'Registration failed'], 500);
    }
}

// Get user profile
function getUserProfile($pdo, $user_id) {
    try {
        $stmt = $pdo->prepare("SELECT id, name, email, created_at FROM users WHERE id = ?");
        $stmt->execute([$user_id]);
        $user = $stmt->fetch(PDO::FETCH_ASSOC);
        
        if (!$user) {
            sendResponse(['success' => false, 'message' => 'User not found'], 404);
            return;
        }
        
        sendResponse(['success' => true, 'user' => $user]);
    } catch (PDOException $e) {
        sendResponse(['success' => false, 'message' => 'Failed to fetch user profile'], 500);
    }
}

// Update user profile
function updateUserProfile($pdo, $user_id) {
    $json = file_get_contents('php://input');
    $data = json_decode($json, true);
    
    if (!$data) {
        sendResponse(['success' => false, 'message' => 'Invalid data format'], 400);
        return;
    }
    
    $allowedFields = ['name', 'email'];
    $updates = [];
    $values = [];
    
    foreach ($allowedFields as $field) {
        if (isset($data[$field]) && !empty($data[$field])) {
            $updates[] = "$field = ?";
            $values[] = $data[$field];
        }
    }
    
    if (empty($updates)) {
        sendResponse(['success' => false, 'message' => 'No valid fields to update'], 400);
        return;
    }
    
    $values[] = $user_id;
    
    try {
        $stmt = $pdo->prepare("UPDATE users SET " . implode(', ', $updates) . " WHERE id = ?");
        $stmt->execute($values);
        
        if ($stmt->rowCount() === 0) {
            sendResponse(['success' => false, 'message' => 'No changes made or user not found'], 404);
            return;
        }
        
        $stmt = $pdo->prepare("SELECT id, name, email, created_at FROM users WHERE id = ?");
        $stmt->execute([$user_id]);
        $user = $stmt->fetch(PDO::FETCH_ASSOC);
        
        sendResponse(['success' => true, 'message' => 'Profile updated successfully', 'user' => $user]);
    } catch (PDOException $e) {
        sendResponse(['success' => false, 'message' => 'Failed to update profile'], 500);
    }
}

// Get all traffic lights submitted by the user
function getUserTrafficLights($pdo, $user_id) {
    try {
        $stmt = $pdo->prepare("SELECT * FROM traffic_lights WHERE user_id = ?");
        $stmt->execute([$user_id]);
        $lights = $stmt->fetchAll(PDO::FETCH_ASSOC);
        
        foreach ($lights as &$light) {
            $light['status'] = calculateLightStatus($light);
        }
        
        sendResponse(['success' => true, 'lights' => $lights]);
    } catch (PDOException $e) {
        sendResponse(['success' => false, 'message' => 'Failed to fetch user traffic lights'], 500);
    }
}

// Validate API key
function validateApiKey($pdo, $api_key) {
    if (empty($api_key)) {
        return false;
    }
    
    try {
        $stmt = $pdo->prepare("SELECT * FROM api_keys WHERE api_key = ? AND active = 1");
        $stmt->execute([$api_key]);
        return $stmt->rowCount() > 0;
    } catch (PDOException $e) {
        return false;
    }
}

// Get all traffic lights
function getAllLights($pdo) {
    try {
        $stmt = $pdo->query("SELECT * FROM traffic_lights WHERE status = 'approved'");
        $lights = $stmt->fetchAll(PDO::FETCH_ASSOC);
        
        foreach ($lights as &$light) {
            $light['status'] = calculateLightStatus($light);
        }
        
        sendResponse(['success' => true, 'lights' => $lights]);
    } catch (PDOException $e) {
        sendResponse(['success' => false, 'message' => 'Failed to fetch traffic lights'], 500);
    }
}

// Get traffic light by ID
function getLightById($pdo, $id) {
    if (!$id) {
        sendResponse(['success' => false, 'message' => 'ID is required'], 400);
        return;
    }
    
    try {
        $stmt = $pdo->prepare("SELECT * FROM traffic_lights WHERE id = ?");
        $stmt->execute([$id]);
        $light = $stmt->fetch(PDO::FETCH_ASSOC);
        
        if ($light) {
            $light['status'] = calculateLightStatus($light);
            sendResponse(['success' => true, 'light' => $light]);
        } else {
            sendResponse(['success' => false, 'message' => 'Traffic light not found'], 404);
        }
    } catch (PDOException $e) {
        sendResponse(['success' => false, 'message' => 'Failed to fetch traffic light'], 500);
    }
}

// Get nearby traffic lights
function getNearbyLights($pdo, $lat, $lng, $radius) {
    if (!$lat || !$lng) {
        sendResponse(['success' => false, 'message' => 'Latitude and longitude are required'], 400);
        return;
    }
    
    try {
        $earth_radius = 6371; // Earth's radius in km
        
        $stmt = $pdo->prepare("
            SELECT *, 
            ($earth_radius * acos(cos(radians(?)) * cos(radians(latitude)) * 
            cos(radians(longitude) - radians(?)) + sin(radians(?)) * 
            sin(radians(latitude)))) AS distance 
            FROM traffic_lights 
            WHERE status = 'approved'
            HAVING distance <= ? 
            ORDER BY distance
        ");
        $stmt->execute([$lat, $lng, $lat, $radius]);
        $lights = $stmt->fetchAll(PDO::FETCH_ASSOC);
        
        foreach ($lights as &$light) {
            $light['status'] = calculateLightStatus($light);
        }
        
        sendResponse(['success' => true, 'lights' => $lights]);
    } catch (PDOException $e) {
        sendResponse(['success' => false, 'message' => 'Failed to fetch nearby traffic lights'], 500);
    }
}

// Add new traffic light
function addLight($pdo, $user_id = null) {
    $json = file_get_contents('php://input');
    $data = json_decode($json, true);
    
    if (!$data) {
        sendResponse(['success' => false, 'message' => 'Invalid data format'], 400);
        return;
    }
    
    $required = ['name', 'latitude', 'longitude', 'direction', 'red_duration', 'green_duration'];
    foreach ($required as $field) {
        if (!isset($data[$field])) {
            sendResponse(['success' => false, 'message' => "$field is required"], 400);
            return;
        }
    }
    
    try {
        $sql = "INSERT INTO traffic_lights 
                (name, latitude, longitude, direction, red_duration, green_duration, user_id, status, created_at) 
                VALUES (?, ?, ?, ?, ?, ?, ?, 'pending', NOW())";
        
        $stmt = $pdo->prepare($sql);
        $stmt->execute([
            $data['name'],
            $data['latitude'],
            $data['longitude'],
            $data['direction'],
            $data['red_duration'],
            $data['green_duration'],
            $user_id
        ]);
        
        $id = $pdo->lastInsertId();
        
        $stmt = $pdo->prepare("SELECT * FROM traffic_lights WHERE id = ?");
        $stmt->execute([$id]);
        $light = $stmt->fetch(PDO::FETCH_ASSOC);
        
        $light['status'] = calculateLightStatus($light);
        
        sendResponse(['success' => true, 'message' => 'Traffic light added successfully', 'light' => $light]);
    } catch (PDOException $e) {
        sendResponse(['success' => false, 'message' => 'Failed to add traffic light'], 500);
    }
}

// Update traffic light
function updateLight($pdo, $id, $user_id = null) {
    $json = file_get_contents('php://input');
    $data = json_decode($json, true);
    
    if (!$data) {
        sendResponse(['success' => false, 'message' => 'Invalid data format'], 400);
        return;
    }
    
    // Verify ownership if user is authenticated
    if ($user_id) {
        $stmt = $pdo->prepare("SELECT user_id FROM traffic_lights WHERE id = ?");
        $stmt->execute([$id]);
        $light = $stmt->fetch(PDO::FETCH_ASSOC);
        
        if (!$light) {
            sendResponse(['success' => false, 'message' => 'Traffic light not found'], 404);
            return;
        }
        
        if ($light['user_id'] != $user_id) {
            // Allow admins to update any light (would need a proper admin check here)
            $stmt = $pdo->prepare("SELECT role FROM users WHERE id = ?");
            $stmt->execute([$user_id]);
            $user = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$user || $user['role'] !== 'admin') {
                sendResponse(['success' => false, 'message' => 'You do not have permission to update this traffic light'], 403);
                return;
            }
        }
    }
    
    $allowedFields = ['name', 'latitude', 'longitude', 'direction', 'red_duration', 'green_duration', 'status'];
    $fields = [];
    $values = [];
    
    foreach ($data as $key => $value) {
        if (in_array($key, $allowedFields)) {
            $fields[] = "$key = ?";
            $values[] = $value;
        }
    }
    
    if (empty($fields)) {
        sendResponse(['success' => false, 'message' => 'No valid fields to update'], 400);
        return;
    }
    
    $values[] = $id;
    
    try {
        $stmt = $pdo->prepare("UPDATE traffic_lights SET " . implode(', ', $fields) . " WHERE id = ?");
        $stmt->execute($values);
        
        if ($stmt->rowCount() === 0) {
            sendResponse(['success' => false, 'message' => 'Traffic light not found or no changes made'], 404);
            return;
        }
        
        $stmt = $pdo->prepare("SELECT * FROM traffic_lights WHERE id = ?");
        $stmt->execute([$id]);
        $light = $stmt->fetch(PDO::FETCH_ASSOC);
        
        $light['status'] = calculateLightStatus($light);
        
        sendResponse(['success' => true, 'message' => 'Traffic light updated successfully', 'light' => $light]);
    } catch (PDOException $e) {
        sendResponse(['success' => false, 'message' => 'Failed to update traffic light'], 500);
    }
}

// Delete traffic light
function deleteLight($pdo, $id, $user_id = null) {
    // Verify ownership if user is authenticated
    if ($user_id) {
        $stmt = $pdo->prepare("SELECT user_id FROM traffic_lights WHERE id = ?");
        $stmt->execute([$id]);
        $light = $stmt->fetch(PDO::FETCH_ASSOC);
        
        if (!$light) {
            sendResponse(['success' => false, 'message' => 'Traffic light not found'], 404);
            return;
        }
        
        if ($light['user_id'] != $user_id) {
            // Allow admins to delete any light (would need a proper admin check here)
            $stmt = $pdo->prepare("SELECT role FROM users WHERE id = ?");
            $stmt->execute([$user_id]);
            $user = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$user || $user['role'] !== 'admin') {
                sendResponse(['success' => false, 'message' => 'You do not have permission to delete this traffic light'], 403);
                return;
            }
        }
    }
    
    try {
        $stmt = $pdo->prepare("DELETE FROM traffic_lights WHERE id = ?");
        $stmt->execute([$id]);
        
        if ($stmt->rowCount() === 0) {
            sendResponse(['success' => false, 'message' => 'Traffic light not found'], 404);
            return;
        }
        
        sendResponse(['success' => true, 'message' => 'Traffic light deleted successfully']);
    } catch (PDOException $e) {
        sendResponse(['success' => false, 'message' => 'Failed to delete traffic light'], 500);
    }
}

// Update traffic light timing
function updateLightTiming($pdo, $user_id = null, $light_id = null) {
    $json = file_get_contents('php://input');
    $data = json_decode($json, true);
    
    if (!$data) {
        sendResponse(['success' => false, 'message' => 'Invalid data format'], 400);
        return;
    }
    
    // Use either ID from endpoint or from request body
    $id = $light_id ?? $data['id'] ?? null;
    
    if (!$id || !isset($data['duration_type']) || !isset($data['duration'])) {
        sendResponse(['success' => false, 'message' => 'ID, duration_type and duration are required'], 400);
        return;
    }
    
    if ($data['duration_type'] !== 'red' && $data['duration_type'] !== 'green') {
        sendResponse(['success' => false, 'message' => 'duration_type must be either red or green'], 400);
        return;
    }
    
    try {
        // First get the current light data
        $stmt = $pdo->prepare("SELECT * FROM traffic_lights WHERE id = ?");
        $stmt->execute([$id]);
        $light = $stmt->fetch(PDO::FETCH_ASSOC);
        
        if (!$light) {
            sendResponse(['success' => false, 'message' => 'Traffic light not found'], 404);
            return;
        }
        
        // Update the appropriate duration field
        $field = $data['duration_type'] . '_duration';
        
        $stmt = $pdo->prepare("UPDATE traffic_lights SET $field = ? WHERE id = ?");
        $stmt->execute([$data['duration'], $id]);
        
        if ($stmt->rowCount() === 0) {
            sendResponse(['success' => false, 'message' => 'No changes made'], 304);
            return;
        }
        
        // Record the measurement in the history table if we have a user ID
        if ($user_id) {
            $stmt = $pdo->prepare("
                INSERT INTO traffic_light_measurements
                (traffic_light_id, user_id, duration_type, duration, measured_at)
                VALUES (?, ?, ?, ?, NOW())
            ");
            $stmt->execute([$id, $user_id, $data['duration_type'], $data['duration']]);
        }
        
        // Get the updated light data
        $stmt = $pdo->prepare("SELECT * FROM traffic_lights WHERE id = ?");
        $stmt->execute([$id]);
        $updatedLight = $stmt->fetch(PDO::FETCH_ASSOC);
        
        $updatedLight['status'] = calculateLightStatus($updatedLight);
        
        sendResponse(['success' => true, 'message' => 'Timing updated successfully', 'light' => $updatedLight]);
    } catch (PDOException $e) {
        sendResponse(['success' => false, 'message' => 'Failed to update timing'], 500);
    }
}

// Calculate the current status of a traffic light
function calculateLightStatus($light) {
    $totalCycle = (int)$light['red_duration'] + (int)$light['green_duration'];
    $currentTime = time();
    $timeInCycle = $currentTime % $totalCycle;
    
    if ($timeInCycle < $light['red_duration']) {
        return [
            'isRed' => true,
            'color' => 'red',
            'label' => 'RED',
            'timeLeft' => $light['red_duration'] - $timeInCycle,
            'nextState' => 'GREEN',
            'cyclePosition' => ($timeInCycle / $totalCycle) * 100
        ];
    } else {
        return [
            'isRed' => false,
            'color' => 'green',
            'label' => 'GREEN',
            'timeLeft' => $totalCycle - $timeInCycle,
            'nextState' => 'RED',
            'cyclePosition' => ($timeInCycle / $totalCycle) * 100
        ];
    }
}

// Generate JWT token
function generateJWTToken($payload) {
    $header = json_encode(['typ' => 'JWT', 'alg' => 'HS256']);
    $payload['iat'] = time(); // Issued at
    $payload['exp'] = time() + (30 * 24 * 60 * 60); // Expires in 30 days
    $payload = json_encode($payload);
    
    $base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header));
    $base64UrlPayload = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($payload));
    
    $signature = hash_hmac('sha256', $base64UrlHeader . "." . $base64UrlPayload, getJWTSecret(), true);
    $base64UrlSignature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature));
    
    return $base64UrlHeader . "." . $base64UrlPayload . "." . $base64UrlSignature;
}

// Verify JWT token
function verifyJWTToken($token) {
    $tokenParts = explode('.', $token);
    if (count($tokenParts) != 3) {
        return null;
    }
    
    list($base64UrlHeader, $base64UrlPayload, $base64UrlSignature) = $tokenParts;
    
    $signature = base64_decode(str_replace(['-', '_'], ['+', '/'], $base64UrlSignature));
    $rawSignature = hash_hmac('sha256', $base64UrlHeader . "." . $base64UrlPayload, getJWTSecret(), true);
    
    if (!hash_equals($signature, $rawSignature)) {
        return null;
    }
    
    $payload = json_decode(base64_decode(str_replace(['-', '_'], ['+', '/'], $base64UrlPayload)), true);
    
    // Check if token is expired
    if (isset($payload->exp) && $payload->exp < time()) {
        return null;
    }
    
    return (array) $payload;
}

// Get JWT secret key
function getJWTSecret() {
    // Ideally, this should be stored in an environment variable
    return 'imators_traffic_light_secret_key_346980';
}

// Send JSON response with appropriate HTTP status code
function sendResponse($data, $statusCode = 200) {
    http_response_code($statusCode);
    echo json_encode($data);
    exit;
}

// Create database tables if they don't exist
function createTables($pdo) {
    try {
        // Traffic lights table
        $pdo->exec("
            CREATE TABLE IF NOT EXISTS traffic_lights (
                id INT AUTO_INCREMENT PRIMARY KEY,
                name VARCHAR(255) NOT NULL,
                latitude DECIMAL(10, 8) NOT NULL,
                longitude DECIMAL(11, 8) NOT NULL,
                direction ENUM('north', 'east', 'south', 'west') NOT NULL,
                red_duration INT NOT NULL,
                green_duration INT NOT NULL,
                user_id INT NULL,
                status ENUM('pending', 'approved', 'rejected') DEFAULT 'pending',
                created_at DATETIME NOT NULL,
                updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                INDEX (user_id),
                INDEX (status)
            )
        ");
        
        // Users table
        $pdo->exec("
            CREATE TABLE IF NOT EXISTS users (
                id INT AUTO_INCREMENT PRIMARY KEY,
                name VARCHAR(255) NOT NULL,
                email VARCHAR(255) NOT NULL UNIQUE,
                password VARCHAR(255) NOT NULL,
                role ENUM('user', 'admin') DEFAULT 'user',
                created_at DATETIME NOT NULL,
                updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                INDEX (email),
                INDEX (role)
            )
        ");
        
        // API keys table
        $pdo->exec("
            CREATE TABLE IF NOT EXISTS api_keys (
                id INT AUTO_INCREMENT PRIMARY KEY,
                api_key VARCHAR(64) NOT NULL UNIQUE,
                description VARCHAR(255) NULL,
                active TINYINT(1) DEFAULT 1,
                created_at DATETIME NOT NULL,
                updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                INDEX (api_key),
                INDEX (active)
            )
        ");
        
        // Traffic light measurements history
        $pdo->exec("
            CREATE TABLE IF NOT EXISTS traffic_light_measurements (
                id INT AUTO_INCREMENT PRIMARY KEY,
                traffic_light_id INT NOT NULL,
                user_id INT NULL,
                duration_type ENUM('red', 'green') NOT NULL,
                duration INT NOT NULL,
                measured_at DATETIME NOT NULL,
                INDEX (traffic_light_id),
                INDEX (user_id)
            )
        ");
        
        return true;
    } catch (PDOException $e) {
        return false;
    }
}

// Create tables on first run
createTables($pdo);