//
//  BSURewardedVideoAd.swift
//  Unity-iPhone
//
//  Created by Moin Hasan on 5/22/25.
//

import Foundation
import BlueStackSDK
import UIKit

@objc(BSURewardedVideoAd)
public class BSURewardedVideoAd: NSObject {
    @objc public var rewardedVideoAdClient: BSUTypeRewardedVideoAdClientRefPointer?
    @objc public var onLoadedCallback: BSUOnRewardedVideoLoadedCallback?
    @objc public var onErrorCallback: BSUOnRewardedVideoErrorCallback?
    @objc public var onClickedCallback: BSUOnRewardedVideoClickedCallback?
    @objc public var onAdClosedCallback: BSUOnRewardedVideoClosedCallback?
    @objc public var onAdAppearedCallback: BSUOnRewardedVideoAppearedCallback?
    @objc public var onRewardEarnedCallback: BSUOnUserRewardEarnedCallback?

    private var rewardedVideoAdFactory: RewardedAd?
    private var showWhenLoaded = false
    
    @objc public init(rewardedClientReference: BSUTypeRewardedVideoAdClientRefPointer?, placementId: String) {
        self.rewardedVideoAdClient = rewardedClientReference
        super.init()
        self.rewardedVideoAdFactory = RewardedAd(placementID: placementId)
        self.rewardedVideoAdFactory?.delegate = self
        self.rewardedVideoAdFactory?.fullScreenDelegate = self
    }

    @objc public func loadAd() {
        DispatchQueue.main.async {
            self.rewardedVideoAdFactory?.load()
        }
    }

    @objc public func loadAd(withRequestOptions requestOptionsRef: BSUTypeRequestOptionsRef) {
        let bsuOptions = Unmanaged<BSURequestOptions>.fromOpaque(requestOptionsRef).takeUnretainedValue()
        let sdkOptions = bsuOptions.toSDKRequestOptions()
        DispatchQueue.main.async {
            self.rewardedVideoAdFactory?.load(requestOptions: sdkOptions)
        }
    }
    
    @objc public func show() {
        if let rewardedVideoAd = self.rewardedVideoAdFactory {
            if rewardedVideoAd.isReady {
                DispatchQueue.main.async {
                    rewardedVideoAd.show(fromRootViewController: self.rewardedVideoAdFactory?.viewController)
                }
            }
        }
    }

    @objc public func destroy() {
        rewardedVideoAdFactory = nil
    }
}

extension BSURewardedVideoAd: RewardedAdDelegate {
    public func onAdLoaded(_ ad: BlueStackSDK.RewardedAd) {
        if showWhenLoaded {
            show()
        }
        onLoadedCallback?(rewardedVideoAdClient)
    }
    
    public func onAdFailedToLoad(_ ad: BlueStackSDK.RewardedAd, _ error: any Error) {
        if let nsError = error as NSError? {
            let errorPointer = Unmanaged.passUnretained(nsError).toOpaque()
            onErrorCallback?(rewardedVideoAdClient, errorPointer)
        } else {
            onErrorCallback?(rewardedVideoAdClient, nil)
        }
    }
    
    public func onRewardEarned(_ ad: BlueStackSDK.RewardedAd, _ reward: BlueStackSDK.Reward?) {
        print("Reward earned!" + String(describing: reward?.currency ?? "unknown") + " " + String(describing: reward?.amount ?? 0))
        if let reward = reward {
            onRewardEarnedCallback?(rewardedVideoAdClient, reward.currency ?? "unknown", Int32(truncating: reward.amount ?? 0))
        }
    }
}

extension BSURewardedVideoAd: FullScreenDelegate {
    public func onAdDisplayed(_ ad: any FullScreenDisplayableAd) {
        onAdAppearedCallback?(rewardedVideoAdClient)
    }

    public func onAdFailedToDisplay(_ ad: any FullScreenDisplayableAd, _ error: any Error) {
        if let nsError = error as NSError? {
            let errorPointer = Unmanaged.passUnretained(nsError).toOpaque()
            onErrorCallback?(rewardedVideoAdClient, errorPointer)
        } else {
            onErrorCallback?(rewardedVideoAdClient, nil)
        }
    }

    public func onAdDismissed(_ ad: any FullScreenDisplayableAd) {
        onAdClosedCallback?(rewardedVideoAdClient)
    }

    public func onAdClicked(_ ad: any FullScreenDisplayableAd) {
        onClickedCallback?(rewardedVideoAdClient)
    }
}
