import Foundation

/// 单调去重状态（design.md Decision 4），线程安全。
///
/// - `.minimal`：全局只做一次（`minimalDone`）。
/// - `.light` / `.heavy`：每 bizType 记录已达最高档；低于等于已达档则不再执行。
/// - 不允许降级重热；仅 manifest version 变化时 ``reset()`` 整体重置。
final class PrewarmDedup {

    private var reached: [String: PrewarmLevel] = [:]
    private var minimalDone = false
    private let lock = NSLock()

    /// 判断本次 `(level, bizType)` 是否应执行（未被去重）。
    func shouldRun(_ level: PrewarmLevel, bizType: String) -> Bool {
        lock.lock()
        defer { lock.unlock() }
        if level == .minimal {
            return !minimalDone
        }
        guard let cur = reached[bizType] else { return true }
        return level.rawValue > cur.rawValue
    }

    /// 标记 `(level, bizType)` 已完成，更新已达档（单调不降）。
    ///
    /// 档位增量补做：任意档位的 execute 都会先跑全局 DNS，故完成后**一律置
    /// `minimalDone = true`**（含直接调 `.light`/`.heavy` 的情形），避免后续 `.minimal` 重复跑 DNS。
    func markDone(_ level: PrewarmLevel, bizType: String) {
        lock.lock()
        defer { lock.unlock() }
        // 任意档位执行后 DNS 已做过 → 置 minimalDone
        minimalDone = true
        if level == .minimal {
            return
        }
        if let cur = reached[bizType] {
            if level.rawValue > cur.rawValue {
                reached[bizType] = level
            }
        } else {
            reached[bizType] = level
        }
    }

    /// 整体重置（manifest version 变化时调用）。
    func reset() {
        lock.lock()
        defer { lock.unlock() }
        reached.removeAll()
        minimalDone = false
    }
}
