<?php

namespace app;

// 应用请求对象类
use app\http\HttpAuth;
use app\http\HttpClient;
use think\exception\ValidateException;
use think\helper\Macroable;

/**
 * @method static HttpClient getClient() 获取客户端信息
 */
class Request extends \think\Request
{
    use Macroable;

    /**
     * @var string
     */
    public string $contextId = '';
    /**
     * @var HttpAuth
     */
    private readonly HttpAuth $auth;

    /**
     * 设置Auth
     * @param HttpAuth $auth
     * @return Request
     */
    public function setAuth(HttpAuth $auth): self
    {
        $this->auth = $auth;
        return $this;
    }

    public function getAuth(): ?HttpAuth
    {
//        var_dump($this->auth);
        return $this->auth ?? null;
    }


    public function getBrowser(): string
    {
        return get_agent_browser($this->server('HTTP_USER_AGENT'));
    }

    public function getDevice(): string
    {
        return get_agent_device($this->server('HTTP_USER_AGENT'));
    }

    public function getOs(): string
    {
        return get_agent_os($this->server('HTTP_USER_AGENT'));
    }

    const string DATA_SECRET_KEY = "mySecretKey123!";
    /**
     * 加密数据
     */
    static function encryptCryptoJSAES($data): string
    {
        // 如果是数组或对象，转换为 JSON 字符串
        if (is_array($data) || is_object($data)) {
            $data = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        }

        // 生成随机 salt (8字节)
        $salt = openssl_random_pseudo_bytes(8);

        // 通过 EVP_BytesToKey 派生密钥和 IV
        $keyIv = self::evpBytesToKey($salt);
        $key = $keyIv['key'];
        $iv = $keyIv['iv'];

//        // 添加 PKCS#7 填充
//        $blockSize = 16; // AES 块大小
//        $padding = $blockSize - (strlen($data) % $blockSize);
//        $data .= str_repeat(chr($padding), $padding);

        // AES-256-CBC 加密
        $encrypted = openssl_encrypt(
            $data,
            'aes-256-cbc',
            $key,
            OPENSSL_RAW_DATA,
            $iv
        );

        // 组合 Salted__ + salt + 加密数据
        $result = "Salted__" . $salt . $encrypted;

        // Base64 编码
        return base64_encode($result);
    }

    /**
     * 解密 CryptoJS 加密的数据
     */
    static function  decryptCryptoJSData(string $encryptedData): string
    {
        // Base64解码
        $data = base64_decode($encryptedData);

        // 检查Salted__头
        if (!str_starts_with($data, "Salted__")) {
            throw new ValidateException('Invalid format: missing "Salted__" header');
        }

        // 提取Salt (8字节)
        $salt = substr($data, 8, 8);
        $ct = substr($data, 16);

        // 通过EVP_BytesToKey派生密钥和IV
        $keyIv = self::evpBytesToKey($salt);
        $key = $keyIv['key'];
        $iv = $keyIv['iv'];

        // AES-256-CBC解密
        return openssl_decrypt(
            $ct,
            'aes-256-cbc',
            $key,
            OPENSSL_RAW_DATA,
            $iv
        );
    }

    static private function evpBytesToKey($salt): array
    {
        $password = self::DATA_SECRET_KEY;
        $bytes = '';
        $last = '';
        // 生成48字节：32字节key + 16字节IV
        while(strlen($bytes) < 48) {
            $last = md5($last . $password . $salt, true);
            $bytes .= $last;
        }
        return [
            'key' => substr($bytes, 0, 32),
            'iv'  => substr($bytes, 32, 16)
        ];
    }
}
