<?php
/**
 * POST /api/rewards/claim.php
 * Body (JSON): { reward_id }
 * Deducts points and issues a redemption code the buyer shows a seller in
 * person at pickup - consistent with the rest of the app, which has no
 * payment gateway and settles everything off-platform.
 */

require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/../includes/response.php';
require_once __DIR__ . '/../includes/auth.php';
require_once __DIR__ . '/../includes/loyalty.php';

only_post_allowed();
$userId = require_login();

$input = get_json_input();
$rewardId = (int) ($input['reward_id'] ?? 0);
if ($rewardId <= 0) {
    send_error('A valid reward_id is required.', 422);
}

$pdo = Database::connect();

try {
    $pdo->beginTransaction();

    $stmt = $pdo->prepare('SELECT id, title, points_cost FROM rewards WHERE id = ? AND is_active = 1 FOR UPDATE');
    $stmt->execute([$rewardId]);
    $reward = $stmt->fetch();
    if (!$reward) {
        $pdo->rollBack();
        send_error('This reward is no longer available.', 404);
    }

    $stmt = $pdo->prepare('SELECT points_balance FROM loyalty_points WHERE user_id = ? FOR UPDATE');
    $stmt->execute([$userId]);
    $balance = (int) ($stmt->fetchColumn() ?: 0);

    if ($balance < (int) $reward['points_cost']) {
        $pdo->rollBack();
        send_error('Not enough points for this reward.', 409);
    }

    // Unique, short, human-typeable redemption code (retry on the rare collision).
    do {
        $code = strtoupper(bin2hex(random_bytes(4))); // 8 hex chars
        $check = $pdo->prepare('SELECT id FROM reward_redemptions WHERE redemption_code = ?');
        $check->execute([$code]);
    } while ($check->fetch());

    award_loyalty_points($pdo, $userId, -1 * (int) $reward['points_cost'], 'Redeemed: ' . $reward['title']);

    $stmt = $pdo->prepare(
        'INSERT INTO reward_redemptions (user_id, reward_id, points_spent, redemption_code) VALUES (?, ?, ?, ?)'
    );
    $stmt->execute([$userId, $rewardId, $reward['points_cost'], $code]);

    $pdo->commit();
} catch (Throwable $e) {
    $pdo->rollBack();
    send_error('Could not redeem this reward. Please try again.', 500, APP_ENV === 'local' ? [$e->getMessage()] : []);
}

send_json(true, 'Reward claimed!', [
    'redemption' => ['code' => $code, 'reward_title' => $reward['title']],
], 201);
