import Nuke
import NukeUI
import SwiftUI

public actor RemoteImagePrefetcher {
    public static let shared = RemoteImagePrefetcher()
    private let pipeline = ImagePipeline.shared
    private let prefetcher = ImagePrefetcher()
    private let timeout: TimeInterval = 10 // 10 seconds

    /// Configures the global ImagePipeline.shared instance.
    /// Must be called on the main thread during app launch to avoid race conditions.
    /// This is a static configuration method to ensure thread-safe initialization of the global singleton.
    @MainActor
    public static func configureNuke() {
        ImagePipeline.shared = ImagePipeline {
            $0.isDecompressionEnabled = true
            $0.isTaskCoalescingEnabled = true
            $0.isStoringPreviewsInMemoryCache = true
        }
    }

    public nonisolated func loadImages(urls: [URL]) {
        prefetcher.startPrefetching(with: urls)
    }

    public nonisolated func loadAndWaitForImages(urls: [URL]) async {
        guard !urls.isEmpty else {
            return
        }

        return await withCheckedContinuation { [self] continuation in
            var didComplete = false
            let shouldComplete = {
                guard !didComplete else { return }
                didComplete = true
                continuation.resume(returning: ())
            }

            let timeoutTask = Task {
                try await Task.sleep(for: .seconds(timeout))
                shouldComplete()
            }

            self.prefetcher.startPrefetching(with: urls)
            self.prefetcher.didComplete = { @MainActor @Sendable in
                timeoutTask.cancel()
                shouldComplete()
                self.prefetcher.didComplete = nil
            }
        }
    }

    public func cachedImage(for url: URL) async throws -> Image? {
        guard let cachedImage = try? await pipeline.image(for: url) else {
            return nil
        }
        return Image(uiImage: cachedImage)
    }

    public func cachedUIImage(for url: URL) async throws -> UIImage? {
        let cachedImage = try? await pipeline.image(for: url)
        return cachedImage
    }

    private init() {}
}
