<?php
// app/docno.php

/**
 * Generates the next document number for a given type (e.g. ODL, INV).
 * Safe to call inside an existing transaction.
 */
function next_doc_no(PDO $pdo, string $type, ?string $date = null): string
{
    if ($date === null) {
        $date = date('Y-m-d');
    }

    $period = date('Y-m', strtotime($date)); // YYYY-MM

    $startedHere = false;

    try {
        if (!$pdo->inTransaction()) {
            $pdo->beginTransaction();
            $startedHere = true;
        }

        // Ensure row exists (no lock needed here)
        $ins = $pdo->prepare(
            "INSERT IGNORE INTO doc_sequences_v2 (doc_type, period, last_no)
             VALUES (?, ?, 0)"
        );
        $ins->execute([$type, $period]);

        // Lock row, read, increment
        $sel = $pdo->prepare(
            "SELECT last_no
             FROM doc_sequences_v2
             WHERE doc_type = ? AND period = ?
             FOR UPDATE"
        );
        $sel->execute([$type, $period]);
        $last = (int)$sel->fetchColumn();

        $next = $last + 1;

        $upd = $pdo->prepare(
            "UPDATE doc_sequences_v2
             SET last_no = ?
             WHERE doc_type = ? AND period = ?"
        );
        $upd->execute([$next, $type, $period]);

        if ($startedHere) {
            $pdo->commit();
        }

        // TYPE-YYYYMM-000001
        return sprintf('%s-%s-%06d', $type, str_replace('-', '', $period), $next);

    } catch (Throwable $e) {
        if ($startedHere && $pdo->inTransaction()) {
            $pdo->rollBack();
        }
        throw $e;
    }
}