<?php

namespace App\Support;

/**
 * Byte counts for humans. WireGuard reports raw octets, and an operator
 * scanning a table needs "1,4 GB", not 1503238553.
 */
final class Bytes
{
    /**
     * Decimal units (1 kB = 1000 B), not binary ones. Traffic and storage are
     * sold in SI gigabytes — by us and by Hetzner — so a 1000 GB allowance has
     * to read as "1 TB" and not as "931 GB", which is what dividing by 1024
     * produced.
     */
    public static function human(int $bytes, int $decimals = 1): string
    {
        if ($bytes < 1000) {
            return $bytes.' B';
        }

        $units = ['kB', 'MB', 'GB', 'TB', 'PB'];
        $power = min((int) floor(log($bytes, 1000)), count($units));
        $value = $bytes / (1000 ** $power);

        // Whole numbers read better without a trailing ",0" — "1 TB", not "1,0 TB".
        $decimals = ($value >= 100 || round($value, $decimals) == floor($value)) ? 0 : $decimals;

        return number_format($value, $decimals, ',', '.').' '.$units[$power - 1];
    }
}
