<?php
declare(strict_types=1);

namespace SafeTun\Backend\Crypto;

final class Base64Url
{
    public static function encode(string $bytes): string
    {
        return rtrim(strtr(base64_encode($bytes), '+/', '-_'), '=');
    }

    public static function decode(string $encoded, ?int $expectedLength = null): string
    {
        if ($encoded === '' || str_contains($encoded, '=') || !preg_match('/^[A-Za-z0-9_-]+$/D', $encoded)) {
            throw new \InvalidArgumentException('Invalid base64url value.');
        }
        $padding = (4 - (strlen($encoded) % 4)) % 4;
        $decoded = base64_decode(strtr($encoded, '-_', '+/') . str_repeat('=', $padding), true);
        if (!is_string($decoded) || self::encode($decoded) !== $encoded) {
            throw new \InvalidArgumentException('Non-canonical base64url value.');
        }
        if ($expectedLength !== null && strlen($decoded) !== $expectedLength) {
            throw new \InvalidArgumentException('Decoded value has an unexpected length.');
        }
        return $decoded;
    }
}
