<?php
session_start();
header('Content-Type: application/json');
if (empty($_SESSION['user'])) { echo json_encode(['success'=>false,'message'=>'Not authenticated']); exit; }
$input = json_decode(file_get_contents('php://input'), true);
$credits = isset($input['credits']) ? (int)$input['credits'] : 0;
$valid = [1,3,5,10,15,20];
if (!in_array($credits, $valid)) { echo json_encode(['success'=>false,'message'=>'Invalid bundle']); exit; }

$prices = [1=>500,3=>1400,5=>2200,10=>4000,15=>5600,20=>7200]; // cents

$root = dirname(__DIR__, 2);
require_once $root . '/bootstrap.php'; // must provide $db

try {
  $db->beginTransaction();
  $stmt = $db->prepare('INSERT INTO purchases (user_id, credits, amount_cents, status) VALUES (?, ?, ?, ?)');
  $stmt->execute([$_SESSION['user']['id'], $credits, $prices[$credits], 'completed']); // mark completed for offline/pay-later
  $purchaseId = $db->lastInsertId();

  $stmt = $db->prepare('INSERT INTO credit_bundles (user_id, credits, credits_remaining, expires_at) VALUES (?, ?, ?, DATE_ADD(NOW(), INTERVAL 1 MONTH))');
  $stmt->execute([$_SESSION['user']['id'], $credits, $credits]);

  $db->commit();
  echo json_encode(['success'=>true,'message'=>'Credits added.', 'purchase_id'=>$purchaseId]);
} catch (Exception $ex) {
  if ($db->inTransaction()) $db->rollBack();
  echo json_encode(['success'=>false,'message'=>'Error: '.$ex->getMessage()]);
}

// Credit consumption helpers (FIFO by expires_at).
// Functions accept a PDO $db instance and do safe row-locking.
// - consume_credits($db, $userId, $amount, $manageTx = true)
//     returns array of used bundles [{id, used}] on success or false on insufficient credits.
// - total_available_credits($db, $userId) returns int

function total_available_credits(PDO $db, int $userId): int {
    $stmt = $db->prepare('SELECT SUM(credits_remaining) AS total FROM credit_bundles WHERE user_id = ? AND credits_remaining > 0 AND expires_at > NOW()');
    $stmt->execute([$userId]);
    $r = $stmt->fetch(PDO::FETCH_ASSOC);
    return $r ? (int)$r['total'] : 0;
}

function consume_credits(PDO $db, int $userId, int $amount, bool $manageTx = true) {
    if ($amount <= 0) return [];

    $started = false;
    try {
        if ($manageTx) { $db->beginTransaction(); $started = true; }

        // Lock candidate bundles (ordered by expiry earliest first).
        $sql = 'SELECT * FROM credit_bundles 
                WHERE user_id = ? AND credits_remaining > 0 AND expires_at > NOW()
                ORDER BY expires_at ASC
                FOR UPDATE';
        $stmt = $db->prepare($sql);
        $stmt->execute([$userId]);
        $bundles = $stmt->fetchAll(PDO::FETCH_ASSOC);

        $available = 0;
        foreach ($bundles as $b) $available += (int)$b['credits_remaining'];
        if ($available < $amount) {
            if ($started) $db->rollBack();
            return false;
        }

        $remaining = $amount;
        $used = [];
        foreach ($bundles as $b) {
            if ($remaining <= 0) break;
            $use = min((int)$b['credits_remaining'], $remaining);
            $newRemain = (int)$b['credits_remaining'] - $use;
            $upd = $db->prepare('UPDATE credit_bundles SET credits_remaining = ? WHERE id = ?');
            $upd->execute([$newRemain, $b['id']]);
            $used[] = ['bundle_id' => (int)$b['id'], 'used' => $use];
            $remaining -= $use;
        }

        if ($remaining > 0) {
            // Shouldn't happen because we checked available earlier, but safe-guard:
            if ($started) $db->rollBack();
            return false;
        }

        if ($started) $db->commit();
        return $used;
        return $used;n $ex) {
    } catch (Exception $ex) {inTransaction()) $db->rollBack();
        if ($started && $db->inTransaction()) $db->rollBack();
        throw $ex;
    }}