//
//  QiniuTokenSigner.swift
//  ylgamehall
//
//  七牛上传 token 客户端自签（HMAC-SHA1 + Base64URL）。
//  与 msext QiniuManager.m:200-230 generateUploadToken 等价算法。
//
//  putPolicy 结构：
//    { "scope": "iosaudio[:key]", "deadline": now + expiresIn }
//  签名流程：
//    putPolicy JSON → Base64URL → HMAC-SHA1(secretKey) → Base64URL
//    → `${AccessKey}:${sign}:${encodedPolicy}`
//
//  ⚠️ 用 CryptoKit（iOS 13+），不依赖 Qiniu SDK，纯 Swift 自签 token。
//

import Foundation
import CryptoKit

/// 七牛上传 token 自签。bucketName 来自 actor `QiniuConfig.shared`，需 await；
/// accessKey / secretKey 是 AppSecrets 同步取，不需要 await。
public enum QiniuTokenSigner {

    /// 生成上传 token。
    /// - Parameters:
    ///   - key: 已废弃参数；保留签名兼容性，但不再写入 putPolicy。daoqi
    ///     QiniuManager.m:207 的 putPolicy.scope 仅含 bucket（限定 bucket、
    ///     允许任意 key），与新外壳上传 key 是分离的两个维度。带 `:key` 后
    ///     缀（限定 key 精确匹配）会让七牛后端校验更严，且与 daoqi 行为不一致
    ///   - expiresIn: token 有效时长（默认 3600 秒）
    public static func uploadToken(key: String? = nil, expiresIn: TimeInterval = 3600) async -> String {
        _ = key  // 参数保留以避免破坏调用方，但不再使用

        // 1. scope 仅含 bucket（对齐 daoqi QiniuManager.m:207）
        //    bucketName 由远端 audio_bucket 动态注入，启动期已校验非空
        let scope = await QiniuConfig.shared.bucketName
        let deadline = Int(Date().timeIntervalSince1970 + expiresIn)

        // 2. putPolicy JSON（daoqi 用默认 options:0，不强制排序）
        let putPolicy: [String: Any] = [
            "scope":    scope,
            "deadline": deadline
        ]
        let policyData = (try? JSONSerialization.data(withJSONObject: putPolicy, options: [])) ?? Data()

        // 3. Base64URL(putPolicy)
        let encodedPolicy = base64URLEncode(policyData)

        // 4. HMAC-SHA1(secretKey, encodedPolicy) → Base64URL
        let secretKeyData = Data(QiniuConfig.secretKey.utf8)
        let key = SymmetricKey(data: secretKeyData)
        let signature = HMAC<Insecure.SHA1>.authenticationCode(
            for: Data(encodedPolicy.utf8),
            using: key
        )
        let encodedSign = base64URLEncode(Data(signature))

        // 5. token = AccessKey:encodedSign:encodedPolicy
        return "\(QiniuConfig.accessKey):\(encodedSign):\(encodedPolicy)"
    }

    /// Base64URL: 标准 Base64 把 + → -、/ → _，**保留末尾 `=` padding**。
    /// 对齐 daoqi QiniuManager.m:240-245 `urlsafeBase64EncodeData:`，七牛后端
    /// decode token 时依赖 padding 还原 base64；删 `=` 会触发 401 bad token。
    private nonisolated static func base64URLEncode(_ data: Data) -> String {
        data.base64EncodedString()
            .replacingOccurrences(of: "+", with: "-")
            .replacingOccurrences(of: "/", with: "_")
    }
}
