import Foundation
@preconcurrency import React

@objc(BBPlayerViewManager)
class BBPlayerViewManager: RCTViewManager, @unchecked Sendable {

    override func view() -> UIView! {
        return MainActor.assumeIsolated { BBPlayerView() }
    }

    override static func requiresMainQueueSetup() -> Bool {
        return true
    }

    @objc override static func moduleName() -> String! {
        return "BBPlayerView"
    }

    // MARK: - Helpers

    private func getView(_ reactTag: NSNumber) -> BBPlayerView? {
        return self.bridge.uiManager.view(forReactTag: reactTag) as? BBPlayerView
    }

    /// Dispatch to main queue and enter @MainActor context for calling UIView methods.
    private func onMainActor(_ work: @MainActor @Sendable @escaping () -> Void) {
        DispatchQueue.main.async {
            MainActor.assumeIsolated(work)
        }
    }

    // MARK: - Commands

    @objc func play(_ reactTag: NSNumber) {
        onMainActor { self.getView(reactTag)?.play() }
    }

    @objc func pause(_ reactTag: NSNumber) {
        onMainActor { self.getView(reactTag)?.pause() }
    }

    @objc func seek(_ reactTag: NSNumber, offsetInSeconds: NSNumber) {
        onMainActor { self.getView(reactTag)?.seek(offsetInSeconds.intValue) }
    }

    @objc func seekRelative(_ reactTag: NSNumber, offsetInSeconds: NSNumber) {
        onMainActor { self.getView(reactTag)?.seekRelative(offsetInSeconds.doubleValue) }
    }

    @objc func setMuted(_ reactTag: NSNumber, muted: Bool) {
        onMainActor { self.getView(reactTag)?.setMuted(muted) }
    }

    @objc func setVolume(_ reactTag: NSNumber, volume: NSNumber) {
        onMainActor { self.getView(reactTag)?.setVolume(volume.doubleValue) }
    }

    @objc func presentModal(_ reactTag: NSNumber) {
        onMainActor { self.getView(reactTag)?.presentModal() }
    }

    @objc func closeModal(_ reactTag: NSNumber) {
        onMainActor { self.getView(reactTag)?.closeModal() }
    }

    @objc func enterFullscreen(_ reactTag: NSNumber) {
        onMainActor { self.getView(reactTag)?.enterFullscreen() }
    }

    @objc func enterFullscreenLandscape(_ reactTag: NSNumber) {
        onMainActor { self.getView(reactTag)?.enterFullscreenLandscape() }
    }

    @objc func exitFullscreen(_ reactTag: NSNumber) {
        onMainActor { self.getView(reactTag)?.exitFullscreen() }
    }

    @objc func collapse(_ reactTag: NSNumber) {
        onMainActor { self.getView(reactTag)?.collapse() }
    }

    @objc func expand(_ reactTag: NSNumber) {
        onMainActor { self.getView(reactTag)?.expand() }
    }

    @objc func autoPlayNextCancel(_ reactTag: NSNumber) {
        onMainActor { self.getView(reactTag)?.autoPlayNextCancel() }
    }

    @objc func destroy(_ reactTag: NSNumber) {
        onMainActor { self.getView(reactTag)?.destroy() }
    }

    @objc func unload(_ reactTag: NSNumber) {
        onMainActor { self.getView(reactTag)?.unload() }
    }

    @objc func showCastPicker(_ reactTag: NSNumber) {
        onMainActor { self.getView(reactTag)?.showCastPicker() }
    }

    @objc func loadWithClipId(_ reactTag: NSNumber, clipId: String?, initiator: String?, autoPlay: Bool, seekTo: NSNumber?) {
        onMainActor { self.getView(reactTag)?.loadWithClipId(clipId ?? "", initiator: initiator, autoPlay: autoPlay, seekTo: seekTo?.doubleValue) }
    }

    @objc func loadWithClipListId(_ reactTag: NSNumber, clipListId: String?, initiator: String?, autoPlay: Bool, seekTo: NSNumber?) {
        onMainActor { self.getView(reactTag)?.loadWithClipListId(clipListId ?? "", initiator: initiator, autoPlay: autoPlay, seekTo: seekTo?.doubleValue) }
    }

    @objc func loadWithProjectId(_ reactTag: NSNumber, projectId: String?, initiator: String?, autoPlay: Bool, seekTo: NSNumber?) {
        onMainActor { self.getView(reactTag)?.loadWithProjectId(projectId ?? "", initiator: initiator, autoPlay: autoPlay, seekTo: seekTo?.doubleValue) }
    }

    @objc func loadWithClipJson(_ reactTag: NSNumber, clipJson: String?, initiator: String?, autoPlay: Bool, seekTo: NSNumber?) {
        onMainActor { self.getView(reactTag)?.loadWithClipJson(clipJson ?? "", initiator: initiator, autoPlay: autoPlay, seekTo: seekTo?.doubleValue) }
    }

    @objc func loadWithClipListJson(_ reactTag: NSNumber, clipListJson: String?, initiator: String?, autoPlay: Bool, seekTo: NSNumber?) {
        onMainActor { self.getView(reactTag)?.loadWithClipListJson(clipListJson ?? "", initiator: initiator, autoPlay: autoPlay, seekTo: seekTo?.doubleValue) }
    }

    @objc func loadWithProjectJson(_ reactTag: NSNumber, projectJson: String?, initiator: String?, autoPlay: Bool, seekTo: NSNumber?) {
        onMainActor { self.getView(reactTag)?.loadWithProjectJson(projectJson ?? "", initiator: initiator, autoPlay: autoPlay, seekTo: seekTo?.doubleValue) }
    }

    @objc func loadWithJsonUrl(_ reactTag: NSNumber, jsonUrl: String?, autoPlay: Bool) {
        onMainActor {
            if let url = jsonUrl {
                self.getView(reactTag)?.loadWithJsonUrl(url, autoPlay: autoPlay)
            }
        }
    }

    // Note: loadWithShortsId is NOT supported on BBPlayerView.
    // For Shorts playback, use the BBShortsView component instead.
}
