<?php
// helpers/barcode_utils.php
// Utilities for generating/validating numeric barcodes (UPC-A by default)

/**
 * Keep only digits from a scanned string (USB scanners sometimes include extra chars).
 */
function digits_only(string $s): string {
    return preg_replace('/\D+/', '', $s) ?? '';
}

/**
 * Calculate UPC-A check digit from an 11-digit numeric string.
 * UPC-A algorithm:
 *  - Sum digits in odd positions (1,3,5,...,11) and multiply by 3
 *  - Add sum of digits in even positions (2,4,...,10)
 *  - Check digit = (10 - (total % 10)) % 10
 */
function upc_a_check_digit(string $elevenDigits): int {
    $elevenDigits = digits_only($elevenDigits);
    if (strlen($elevenDigits) !== 11) {
        throw new InvalidArgumentException('UPC-A check digit requires 11 digits');
    }

    $oddSum = 0;
    $evenSum = 0;
    for ($i = 0; $i < 11; $i++) {
        $d = (int)$elevenDigits[$i];
        $pos = $i + 1; // 1-indexed
        if (($pos % 2) === 1) $oddSum += $d;
        else $evenSum += $d;
    }
    $total = ($oddSum * 3) + $evenSum;
    return (10 - ($total % 10)) % 10;
}

/**
 * Generate a UPC-A (12 digits) based on a fixed prefix + the product id.
 *
 * NOTE: This is an INTERNAL barcode generator. If you need GS1-compliant UPCs,
 * you must use an assigned company prefix.
 */
function generate_upc_a_from_product_id(int $productId, string $prefix = '200'): string {
    if ($productId <= 0) throw new InvalidArgumentException('Invalid product id');
    $prefix = digits_only($prefix);
    if ($prefix === '') $prefix = '200';

    // Build 11 digits: prefix + (11-len(prefix)) digits of product id
    $bodyLen = 11 - strlen($prefix);
    if ($bodyLen <= 0) {
        throw new InvalidArgumentException('Prefix too long for UPC-A');
    }

    // If product id is too large, we still keep the last N digits.
    $idDigits = digits_only((string)$productId);
    if (strlen($idDigits) > $bodyLen) {
        $idDigits = substr($idDigits, -$bodyLen);
    }
    $base11 = $prefix . str_pad($idDigits, $bodyLen, '0', STR_PAD_LEFT);

    $check = upc_a_check_digit($base11);
    return $base11 . (string)$check;
}

/**
 * Validate a UPC-A barcode (12 digits).
 */
function is_valid_upc_a(string $twelveDigits): bool {
    $twelveDigits = digits_only($twelveDigits);
    if (strlen($twelveDigits) !== 12) return false;
    $base11 = substr($twelveDigits, 0, 11);
    $check = (int)substr($twelveDigits, 11, 1);
    try {
        return upc_a_check_digit($base11) === $check;
    } catch (Throwable $e) {
        return false;
    }
}