#if os(macOS)
import Foundation

extension OpenAIDashboardBrowserCookieImporter {
    private struct PendingCookieStoreMutation {
        let token: UUID
        let task: Task<Void, Never>
    }

    @MainActor private static var pendingCookieStoreMutations: [ObjectIdentifier: PendingCookieStoreMutation] = [:]
    private nonisolated static let cookieCacheQueue = DispatchQueue(
        label: "com.steipete.codexbar.openai-cookie-cache")
    private nonisolated static let deadlineQueue = DispatchQueue(
        label: "com.steipete.codexbar.openai-cookie-deadline",
        qos: .userInitiated)

    private final class CookieLoadCompletion: @unchecked Sendable {
        private let lock = NSLock()
        private var didFinish = false

        func finish(_ action: () -> Void) {
            let shouldFinish = self.lock.withLock {
                guard !self.didFinish else { return false }
                self.didFinish = true
                return true
            }
            if shouldFinish { action() }
        }
    }

    nonisolated static func remainingTimeout(
        until deadline: Date?,
        cappedAt localLimit: TimeInterval? = nil,
        now: Date = Date()) throws -> TimeInterval
    {
        guard let deadline else {
            return localLimit.map(OpenAIDashboardFetcher.sanitizedTimeout) ?? .greatestFiniteMagnitude
        }
        let remaining = deadline.timeIntervalSince(now)
        guard remaining > 0 else { throw URLError(.timedOut) }
        guard let localLimit else { return remaining }
        return min(OpenAIDashboardFetcher.sanitizedTimeout(localLimit), remaining)
    }

    nonisolated static func runBoundedCookieLoad<T: Sendable>(
        deadline: Date?,
        timeoutObserver: (@Sendable () -> Void)? = nil,
        operation: @escaping @Sendable () throws -> T) async throws -> T
    {
        // The detached/GCD loader does not inherit TaskLocal prompt policy or retry selection.
        let contextualOperation = BrowserCookieAccessGate.operationPreservingAccessContext(operation)
        guard let deadline else {
            return try await Task.detached(priority: .userInitiated, operation: contextualOperation).value
        }
        let timeout = try self.remainingTimeout(until: deadline)
        let completion = CookieLoadCompletion()
        return try await withCheckedThrowingContinuation { continuation in
            DispatchQueue.global(qos: .userInitiated).async {
                let result = Result(catching: contextualOperation)
                completion.finish { continuation.resume(with: result) }
            }
            self.deadlineQueue.asyncAfter(deadline: .now() + timeout) {
                completion.finish {
                    timeoutObserver?()
                    continuation.resume(throwing: URLError(.timedOut))
                }
            }
        }
    }

    nonisolated static func runBoundedCookieCacheOperation<T: Sendable>(
        deadline: Date?,
        operation: @escaping @Sendable () throws -> T) async throws -> T
    {
        guard let deadline else {
            return try await withCheckedThrowingContinuation { continuation in
                self.cookieCacheQueue.async {
                    continuation.resume(with: Result(catching: operation))
                }
            }
        }

        let timeout = try self.remainingTimeout(until: deadline)
        let completion = CookieLoadCompletion()
        return try await withCheckedThrowingContinuation { continuation in
            self.cookieCacheQueue.async {
                let result = Result(catching: operation)
                completion.finish { continuation.resume(with: result) }
            }
            self.deadlineQueue.asyncAfter(deadline: .now() + timeout) {
                completion.finish { continuation.resume(throwing: URLError(.timedOut)) }
            }
        }
    }

    static func runBoundedCallback(
        deadline: Date?,
        timeoutObserver: (@Sendable () -> Void)? = nil,
        start: (@escaping @Sendable () -> Void) -> Void) async throws
    {
        let completion = CookieLoadCompletion()
        guard let deadline else {
            await withCheckedContinuation { continuation in
                start {
                    completion.finish { continuation.resume() }
                }
            }
            return
        }

        let timeout = try self.remainingTimeout(until: deadline)
        try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<Void, Error>) in
            start {
                completion.finish { continuation.resume() }
            }
            self.deadlineQueue.asyncAfter(deadline: .now() + timeout) {
                completion.finish {
                    timeoutObserver?()
                    continuation.resume(throwing: URLError(.timedOut))
                }
            }
        }
    }

    static func runBoundedValueCallback<T: Sendable>(
        deadline: Date?,
        timeoutObserver: (@Sendable () -> Void)? = nil,
        start: (@escaping @Sendable (T) -> Void) -> Void) async throws -> T
    {
        let completion = CookieLoadCompletion()
        guard let deadline else {
            return await withCheckedContinuation { continuation in
                start { value in
                    completion.finish { continuation.resume(returning: value) }
                }
            }
        }

        let timeout = try self.remainingTimeout(until: deadline)
        return try await withCheckedThrowingContinuation { continuation in
            start { value in
                completion.finish { continuation.resume(returning: value) }
            }
            self.deadlineQueue.asyncAfter(deadline: .now() + timeout) {
                completion.finish {
                    timeoutObserver?()
                    continuation.resume(throwing: URLError(.timedOut))
                }
            }
        }
    }

    static func runSerializedCallback(
        key: ObjectIdentifier,
        deadline: Date?,
        start: @escaping (@escaping @Sendable () -> Void) -> Void) async throws
    {
        while let pending = self.pendingCookieStoreMutations[key] {
            try await self.waitForMutation(pending.task, deadline: deadline)
            if self.pendingCookieStoreMutations[key]?.token == pending.token {
                self.pendingCookieStoreMutations[key] = nil
            }
        }

        let token = UUID()
        let task = Task { @MainActor in
            await withCheckedContinuation { continuation in
                start { continuation.resume() }
            }
        }
        self.pendingCookieStoreMutations[key] = PendingCookieStoreMutation(token: token, task: task)
        Task { @MainActor in
            await task.value
            if self.pendingCookieStoreMutations[key]?.token == token {
                self.pendingCookieStoreMutations[key] = nil
            }
        }
        try await self.waitForMutation(task, deadline: deadline)
    }

    private static func waitForMutation(_ task: Task<Void, Never>, deadline: Date?) async throws {
        try await self.runBoundedCallback(deadline: deadline) { completion in
            Task { @MainActor in
                await task.value
                completion()
            }
        }
    }
}
#endif
