<?php
function nextInvoiceNo(PDO $pdo, int $year): string {
  $pdo->beginTransaction();
  try {
    // row lock (InnoDB)
    $stmt = $pdo->prepare("SELECT last_number FROM invoice_counters WHERE year = :y FOR UPDATE");
    $stmt->execute([':y' => $year]);
    $row = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$row) {
      $last = 0;
      $pdo->prepare("INSERT INTO invoice_counters (year, last_number) VALUES (:y, 0)")
          ->execute([':y' => $year]);
    } else {
      $last = (int)$row['last_number'];
    }

    $next = $last + 1;
    $pdo->prepare("UPDATE invoice_counters SET last_number = :n WHERE year = :y")
        ->execute([':n' => $next, ':y' => $year]);

    $pdo->commit();

    return sprintf("RE-%d-%04d", $year, $next);
  } catch (Throwable $e) {
    $pdo->rollBack();
    throw $e;
  }
}
