<?php
require_once '../config.php';
require_once '../middleware.php';

### API Blueprint: /user/promocode
# POST /user/promocode
# Description: Applies a promo code to award coins.
# Headers:
#   - Device-ID: <device_id> (required)
#   - Session-Token: <session_token> (required)
# Request Body:
#   - user_id: integer (required)
#   - code: string (required)
# Response:
#   - 200: Success
#     {
#       "status": 200,
#       "message": "Promo code applied",
#       "data": {
#         "coins": 100
#       },
#       "new_session_token": "new_strong_session_token_64_chars"
#     }
#   - 400: Invalid input, Invalid promo code, Promo code expired, Usage limit reached, Already used
#   - 401: Unauthorized
#   - 429: Too many requests
#   - 500: Database connection failed

$device_id = $_SERVER['HTTP_DEVICE_ID'] ?? '';
$session_token = $_SERVER['HTTP_SESSION_TOKEN'] ?? '';

$method = $_SERVER['REQUEST_METHOD'];

if ($method === 'POST') {
    // Get the encrypted payload
    $encrypted_payload = file_get_contents('php://input');
    if (empty($encrypted_payload)) {
        sendResponse(400, 'Empty request body');
    }

    // Decrypt the payload
    $data = decryptRequestPayload($encrypted_payload);
    if (!$data) {
        sendResponse(400, 'Invalid request body');
    }

    // Validation for required fields
    if (empty($data['user_id']) || empty($data['code'])) {
        sendResponse(400, 'Missing user_id or code');
    }

    validateInput($data, ['user_id', 'code']);
    $user_id = $data['user_id'];
    $code = $data['code'];

    authenticateSession($user_id, $device_id, $session_token);
    rateLimit($user_id);
    $new_session_token = generateNewSessionToken($user_id, $device_id);

    $conn = getDbConnection();
    $conn->begin_transaction();

    try {
        // Check promo code
        $stmt = $conn->prepare("SELECT id, coins, usage_limit, expiry_date FROM promo_codes WHERE code = ?");
        $stmt->bind_param("s", $code);
        $stmt->execute();
        $result = $stmt->get_result();

        if ($result->num_rows === 0) {
            $new_session_token = generateNewSessionToken($user_id, $device_id);
            sendResponse(400, 'Invalid promo code', [], $new_session_token);
        }

        $promo = $result->fetch_assoc();
        $promo_id = $promo['id'];

        if (strtotime($promo['expiry_date']) < time()) {
            $new_session_token = generateNewSessionToken($user_id, $device_id);
            sendResponse(400, 'Promo code expired', [], $new_session_token);
        }

        // Check usage limit
        $stmt = $conn->prepare("SELECT COUNT(*) as usage_count FROM promo_code_usage WHERE promo_code_id = ?");
        $stmt->bind_param("i", $promo_id);
        $stmt->execute();
        $result = $stmt->get_result();
        $usage = $result->fetch_assoc();

        if ($usage['usage_count'] >= $promo['usage_limit']) {
            $new_session_token = generateNewSessionToken($user_id, $device_id);
            sendResponse(400, 'Promo code usage limit reached', [], $new_session_token);
        }

        // Check if user already used this promo code
        $stmt = $conn->prepare("SELECT id FROM promo_code_usage WHERE user_id = ? AND promo_code_id = ?");
        $stmt->bind_param("ii", $user_id, $promo_id);
        $stmt->execute();
        $result = $stmt->get_result();

        if ($result->num_rows > 0) {
            $new_session_token = generateNewSessionToken($user_id, $device_id);
            sendResponse(400, 'Promo code already used by this user', [], $new_session_token);
        }

        // Award coins
        $stmt = $conn->prepare("UPDATE users SET coins = coins + ? WHERE id = ?");
        $stmt->bind_param("ii", $promo['coins'], $user_id);
        $stmt->execute();

        // Record promo code usage
        $stmt = $conn->prepare("INSERT INTO promo_code_usage (user_id, promo_code_id) VALUES (?, ?)");
        $stmt->bind_param("ii", $user_id, $promo_id);
        $stmt->execute();

        $conn->commit();

        // Fetch the user's updated coin balance
        $stmt_get_coins = $conn->prepare("SELECT coins FROM users WHERE id = ?");
        $stmt_get_coins->bind_param("i", $user_id);
        $stmt_get_coins->execute();
        $result_get_coins = $stmt_get_coins->get_result();
        $user_coins = $result_get_coins->fetch_assoc();
        $stmt_get_coins->close();
        
        sendResponse(200, 'Promo code applied', ['coins_awarded' => $promo['coins'], 'coins' => $user_coins['coins']], $new_session_token);
    } catch (Exception $e) {
        $conn->rollback();
        sendResponse(500, 'Failed to apply promo code: ' . $e->getMessage());
    }

    $stmt->close();
    $conn->close();
} else {
    sendResponse(405, 'Method Not Allowed');
}
?>