<?php

declare(strict_types=1);

namespace Kylin\Ecommerce\Services;

use Illuminate\Support\Facades\Crypt;

/**
 * 电子签名服务
 *
 * 依据《中华人民共和国电子签名法》(2019.4.23 修订)：
 * - 第十四条：可靠的电子签名与手写签名或者盖章具有同等的法律效力
 * - 第十三条：可靠的电子签名需满足签名人专有、仅由签名人控制、签名后不可篡改等条件
 *
 * 依据《电子商务法》第四十九条：
 * 订单生成即合同成立，电子合同需支持电子签名，确保合同效力。
 *
 * 使用方式：
 *   $signature = ESignatureService::sign($userId, $contractData);
 *   $isValid   = ESignatureService::verify($contractData, $signature);
 */
final class ESignatureService
{
    /**
     * 对合同数据进行电子签名
     *
     * 生成基于 HMAC-SHA256 的签名，确保：
     * 1. 签名人专有（签名密钥与用户绑定）
     * 2. 签名后不可篡改（签名覆盖完整合同数据）
     * 3. 签名时可追溯（记录签名时间戳和 IP）
     *
     * @param int|string $userId 签名人 ID
     * @param array $contractData 合同数据（含订单号、金额、商品信息等）
     * @return array{signature: string, signed_at: string, signer_ip: string, law: string}
     */
    public static function sign(int|string $userId, array $contractData): array
    {
        // 合同数据标准化排序（确保相同数据生成相同签名）
        ksort($contractData);

        // 生成签名密钥（与用户绑定）
        $signKey = self::getSignKey($userId);

        // 合同数据序列化
        $payload = json_encode($contractData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

        // HMAC-SHA256 签名
        $signature = hash_hmac('sha256', $payload, $signKey);

        return [
            'signature' => $signature,
            'signed_at' => now()->toIso8601String(),
            'signer_ip' => request()->ip(),
            'signer_id' => $userId,
            'hash_algorithm' => 'HMAC-SHA256',
            'contract_hash' => hash('sha256', $payload),
            'law' => '《中华人民共和国电子签名法》第十三条、第十四条',
        ];
    }

    /**
     * 验证电子签名
     *
     * @param int|string $userId 签名人 ID
     * @param array $contractData 原始合同数据
     * @param string $signature 待验证的签名
     * @return bool
     */
    public static function verify(int|string $userId, array $contractData, string $signature): bool
    {
        ksort($contractData);
        $payload = json_encode($contractData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        $signKey = self::getSignKey($userId);
        $expectedSignature = hash_hmac('sha256', $payload, $signKey);

        return hash_equals($expectedSignature, $signature);
    }

    /**
     * 验证合同未被篡改
     *
     * @param array $contractData 当前合同数据
     * @param string $contractHash 原始合同哈希
     * @return bool
     */
    public static function verifyIntegrity(array $contractData, string $contractHash): bool
    {
        ksort($contractData);
        $payload = json_encode($contractData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        $currentHash = hash('sha256', $payload);

        return hash_equals($contractHash, $currentHash);
    }

    /**
     * 生成合同快照（用于后续防篡改验证）
     *
     * @param array $contractData 合同数据
     * @return array{hash: string, snapshot: array, created_at: string}
     */
    public static function snapshot(array $contractData): array
    {
        ksort($contractData);
        $payload = json_encode($contractData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

        return [
            'hash' => hash('sha256', $payload),
            'snapshot' => $contractData,
            'created_at' => now()->toIso8601String(),
            'law' => '《中华人民共和国电子签名法》第十四条',
        ];
    }

    /**
     * 获取用户签名密钥
     *
     * 签名密钥与用户绑定，确保签名人专有。
     * 密钥派生自用户唯一标识和应用密钥，防止暴力破解。
     *
     * @param int|string $userId
     * @return string
     */
    private static function getSignKey(int|string $userId): string
    {
        // 使用应用密钥 + 用户 ID 派生签名密钥
        $appKey = config('app.key');
        return hash_hmac('sha256', (string) $userId, $appKey);
    }
}