<?php

declare(strict_types=1);

namespace App\Support;

/**
 * URL/Query 传入的 AES-256-GCM 密文 Token 解包为内层 JWT 明文字符串。
 *
 * 约定：Base64( IV(12) ‖ ciphertext ‖ tag(16) )，明文为 UTF-8 JWT（三点分段）。
 * 密钥：`config('lottery.player_auth.aes.key_base64')` Base64 解码后为 32 字节。
 */
final class PlayerTokenAesUnwrap
{
    /**
     * @return 内层 JWT 或 null（未启用/格式错/解密失败）
     */
    public static function tryUnwrap(string $opaque): ?string
    {
        $keyB64 = config('lottery.player_auth.aes.key_base64');
        if (! is_string($keyB64) || trim($keyB64) === '') {
            return null;
        }

        $keyRaw = base64_decode(trim($keyB64), true);
        if (! is_string($keyRaw) || strlen($keyRaw) !== 32) {
            return null;
        }
        $trim = trim($opaque);
        if ($trim === '') {
            return null;
        }

        $bin = base64_decode(strtr($trim, '-_', '+/'), true);
        if ($bin === false || strlen($bin) < 12 + 1 + 16) {
            return null;
        }

        $iv = substr($bin, 0, 12);
        $tag = substr($bin, -16);
        $cipher = substr($bin, 12, -16);

        $plain = openssl_decrypt($cipher, 'aes-256-gcm', $keyRaw, OPENSSL_RAW_DATA, $iv, $tag);
        if (! is_string($plain) || $plain === '') {
            return null;
        }

        return self::looksLikeJwt($plain) ? $plain : null;
    }

    private static function looksLikeJwt(string $s): bool
    {
        return preg_match('/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/', $s) === 1;
    }
}
