//
//  QiniuConfig.swift
//  ylgamehall
//
//  七牛云配置访问层。
//
//  数据来源（单一真相）：
//    - accessKey / secretKey ← AppSecrets.plist（应用级凭证，跨渠道相同）
//    - bucketName / cdnDomain ← RemoteConfig 顶层 audio_bucket / audio_domain
//      （远端动态下发，缺失启动期致命，由 WebContainerViewController 校验后
//      调用 update(domain:bucket:) 注入）
//
//  ⚠️ secretKey 客户端持有 = 父项目 CLAUDE.md「已识别但接受的安全风险」，
//  同款 wxAppSecret 路径。msext 已分发多年等价泄露，沿用不引入新攻击面。
//

import Foundation

/// 七牛云配置访问层。actor 隔离让远端注入的 cdnDomain / bucketName 在并发上传场景下
/// 写读安全。accessKey / secretKey 是 nonisolated immutable，无需 actor 屏障。
public actor QiniuConfig {

    public static let shared = QiniuConfig()

    // MARK: - 来自 AppSecrets.plist（应用级，启动期一次性加载，运行期不变）

    /// 七牛 AccessKey — 来源 `AppSecrets.plist.qiniuAccessKey`
    public nonisolated static var accessKey: String { AppSecrets.shared.qiniuAccessKey }

    /// 七牛 SecretKey — 来源 `AppSecrets.plist.qiniuSecretKey`。HMAC-SHA1 签 putPolicy 用
    public nonisolated static var secretKey: String { AppSecrets.shared.qiniuSecretKey }

    /// 录音 key 模板前缀（msext QiniuConfig.m:22 为空字符串）
    public nonisolated static let recordingDirectory = ""

    // MARK: - 来自 RemoteConfig（远端，启动期动态注入）

    private var _cdnDomain: String = ""
    private var _bucketName: String = ""

    /// 启动期由 WebContainerViewController 在远端配置拉到且校验非空后调用，
    /// 之后 QiniuUploader / QiniuTokenSigner 即可 await 读取。
    public func update(cdnDomain: String, bucketName: String) {
        _cdnDomain = cdnDomain
        _bucketName = bucketName
    }

    /// CDN 域名（不带 http:// 协议头）。访问前必须先 `update(...)`，否则返回空串
    /// 导致后续上传/拼 URL 失败 —— 但启动流水线已保证 update 一定先于任何上传调用
    public var cdnDomain: String { _cdnDomain }

    /// 七牛 bucket 名（putPolicy.scope）。访问前必须先 `update(...)`。
    public var bucketName: String { _bucketName }

    /// 拼访问 URL：`http://{cdnDomain}/{key}`（msext QiniuManager.m:197 等价）
    /// 协议头固定 http://（与 msext 一致；七牛 CDN 同时支持 https，按需评估）。
    public func publicURL(forKey key: String) -> String {
        "http://\(_cdnDomain)/\(key)"
    }
}
