//
//  OnceContinuation.swift
//  Tun
//
//  Created by Codex on 2026/5/7.
//

import Foundation

final class OnceContinuation<Value, Failure: Error>: @unchecked Sendable {
    private let lock = NSLock()
    private var continuation: CheckedContinuation<Value, Failure>?
    private var result: Result<Value, Failure>?

    func set(_ continuation: CheckedContinuation<Value, Failure>) {
        lock.lock()
        if let result {
            lock.unlock()
            continuation.resume(with: result)
            return
        }

        let hasPendingContinuation = self.continuation != nil
        if !hasPendingContinuation {
            self.continuation = continuation
        }
        lock.unlock()

        if hasPendingContinuation {
            preconditionFailure("OnceContinuation can only store one pending continuation")
        }
    }

    func resume(returning value: Value) {
        resume(with: .success(value))
    }

    func resume(throwing error: Failure) {
        resume(with: .failure(error))
    }

    func resume(with result: Result<Value, Failure>) {
        lock.lock()
        guard self.result == nil else {
            lock.unlock()
            return
        }

        self.result = result
        let continuation = self.continuation
        self.continuation = nil
        lock.unlock()

        continuation?.resume(with: result)
    }
}
