import Foundation
import UIKit
import AdsFramework

@_silgen_name("UnitySendMessage")
func UnitySendMessage(_ obj: UnsafePointer<CChar>, _ method: UnsafePointer<CChar>, _ msg: UnsafePointer<CChar>)

@objc public class AdsterUnity: NSObject {
    @objc public static let shared = AdsterUnity()
    private var interstitialLoader: AdSterAdLoader?
    private var currentInterstitialAd: MediationInterstitialAd?
    private var rewardedLoader: AdSterAdLoader?
    private var currentRewardedAd: MediationRewardedAd?
    private var rewardedInterstitialLoader: AdSterAdLoader?
    private var currentRewardedInterstitialAd: MediationRewardedInterstitialAd?
    private var bannerLoader: AdSterAdLoader?
    private var currentBannerAd: MediationBannerAd?
    private var bannerView: UIView?
    private var interstitialImpressionSent = false
    private var rewardedImpressionSent = false
    private var rewardedInterstitialImpressionSent = false
    private var bannerImpressionSent = false

    private override init() { super.init() }

    @objc public func printHelloSwift() { print("hello swift") }

    @objc public func initializeSDK() {
        print("initializeSDK AdsterUnit.swift")
        AdSter.sharedInstance().start(completionHandler: { status in
            print("Ad initialized \(status)")
            let statusStr = String(describing: status)
            UnitySendMessage("AdsterManager", "HandleInitialized", statusStr)
        })
    }

    @objc public func loadInterstitialAd(_ placementKey: String) {
        print("Loading interstitial ad with placement: \(placementKey)")
        guard let viewController = getTopViewController() else { UnitySendMessage("AdsterManager", "HandleInterstitialAdLoadFailed", "No view controller"); return }
        currentInterstitialAd = nil
        interstitialImpressionSent = false
        interstitialLoader = AdSterAdLoader(); interstitialLoader?.delegate = self
        let cfg = AdRequestConfiguration(placement: placementKey, viewController: viewController, publisherProvidedId: "unity_interstitial", customTargetingValues: ["ad_type":"interstitial"])
        interstitialLoader?.loadAd(adRequestConfiguration: cfg)
    }

    @objc public func showInterstitialAd() {
        guard let ad = currentInterstitialAd, let vc = getTopViewController() else { UnitySendMessage("AdsterManager", "HandleInterstitialAdShowFailed", "No ad loaded"); return }
        ad.eventDelegate = self
        ad.presentInterstitial(from: vc)
    }

    @objc public func loadBannerAd(_ placementKey: String) {
        guard let viewController = getTopViewController() else { UnitySendMessage("AdsterBannerAd", "HandleBannerAdLoadFailed", "No view controller"); return }
        destroyBannerAd()
        bannerLoader = AdSterAdLoader(); bannerLoader?.delegate = self
        let cfg = AdRequestConfiguration(placement: placementKey, viewController: viewController, publisherProvidedId: "unity_banner", customTargetingValues: ["ad_type":"banner"])
        bannerLoader?.loadAd(adRequestConfiguration: cfg)
    }

    @objc public func showBannerAd(_ placement: Int) {
        guard let bannerAd = currentBannerAd, let bView = bannerAd.view, let vc = getTopViewController() else { UnitySendMessage("AdsterBannerAd", "HandleBannerAdShowFailed", "No ad loaded"); return }
        bView.removeFromSuperview(); vc.view.addSubview(bView)
        positionBannerView(bView, in: vc.view, placement: placement)
        bannerAd.eventDelegate = self
        UnitySendMessage("AdsterBannerAd", "HandleBannerAdShown", "Success")
    }

    @objc public func hideBannerAd() { if let b = bannerView { b.isHidden = true; UnitySendMessage("AdsterBannerAd", "HandleBannerAdHidden", "Success") } }
    @objc public func destroyBannerAd() { if let b = bannerView { b.removeFromSuperview(); bannerView = nil }; currentBannerAd = nil; bannerLoader = nil; UnitySendMessage("AdsterBannerAd", "HandleBannerAdDestroyed", "Success") }

    private func positionBannerView(_ bannerView: UIView, in parentView: UIView, placement: Int) {
        bannerView.translatesAutoresizingMaskIntoConstraints = false
        bannerView.removeFromSuperview(); parentView.addSubview(bannerView)
        switch placement {
        case 0: NSLayoutConstraint.activate([bannerView.topAnchor.constraint(equalTo: parentView.safeAreaLayoutGuide.topAnchor), bannerView.leadingAnchor.constraint(equalTo: parentView.safeAreaLayoutGuide.leadingAnchor)])
        case 1: NSLayoutConstraint.activate([bannerView.topAnchor.constraint(equalTo: parentView.safeAreaLayoutGuide.topAnchor), bannerView.centerXAnchor.constraint(equalTo: parentView.centerXAnchor)])
        case 2: NSLayoutConstraint.activate([bannerView.topAnchor.constraint(equalTo: parentView.safeAreaLayoutGuide.topAnchor), bannerView.trailingAnchor.constraint(equalTo: parentView.safeAreaLayoutGuide.trailingAnchor)])
        case 3: NSLayoutConstraint.activate([bannerView.bottomAnchor.constraint(equalTo: parentView.safeAreaLayoutGuide.bottomAnchor), bannerView.leadingAnchor.constraint(equalTo: parentView.safeAreaLayoutGuide.leadingAnchor)])
        case 5: NSLayoutConstraint.activate([bannerView.bottomAnchor.constraint(equalTo: parentView.safeAreaLayoutGuide.bottomAnchor), bannerView.trailingAnchor.constraint(equalTo: parentView.safeAreaLayoutGuide.trailingAnchor)])
        default: NSLayoutConstraint.activate([bannerView.bottomAnchor.constraint(equalTo: parentView.safeAreaLayoutGuide.bottomAnchor), bannerView.centerXAnchor.constraint(equalTo: parentView.centerXAnchor)])
        }
    }

    @objc public func loadRewardedAd(_ placementKey: String) {
        guard let viewController = getTopViewController() else { UnitySendMessage("AdsterRewardedAd", "HandleRewardedAdLoadFailed", "No view controller"); return }
        currentRewardedAd = nil; rewardedImpressionSent = false
        rewardedLoader = AdSterAdLoader(); rewardedLoader?.delegate = self
        let cfg = AdRequestConfiguration(placement: placementKey, viewController: viewController, publisherProvidedId: "unity_rewarded", customTargetingValues: ["ad_type":"rewarded"])
        rewardedLoader?.loadAd(adRequestConfiguration: cfg)
    }

    @objc public func showRewardedAd() {
        guard let ad = currentRewardedAd, let vc = getTopViewController() else { UnitySendMessage("AdsterRewardedAd", "HandleRewardedAdShowFailed", "No ad loaded"); return }
        ad.eventDelegate = self
        ad.presentRewarded(from: vc)
    }
    
    @objc public func loadRewardedInterstitialAd(_ placementKey: String) {
        guard let viewController = getTopViewController() else { UnitySendMessage("AdsterRewardedInterstitialAd", "HandleRewardedInterstitialAdLoadFailed", "No view controller"); return }
        currentRewardedInterstitialAd = nil; rewardedInterstitialImpressionSent = false
        rewardedInterstitialLoader = AdSterAdLoader(); rewardedInterstitialLoader?.delegate = self
        let cfg = AdRequestConfiguration(placement: placementKey, viewController: viewController, publisherProvidedId: "unity_rewarded_interstitial", customTargetingValues: ["ad_type":"rewarded_interstitial"])
        rewardedInterstitialLoader?.loadAd(adRequestConfiguration: cfg)
    }
    
    @objc public func showRewardedInterstitialAd() {
        guard let ad = currentRewardedInterstitialAd, let vc = getTopViewController() else { UnitySendMessage("AdsterRewardedInterstitialAd", "HandleRewardedInterstitialAdShowFailed", "No ad loaded"); return }
        ad.eventDelegate = self
        ad.presentRewardedInterstitial(from: vc)
    }

    private func getTopViewController() -> UIViewController? {
        guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let window = windowScene.windows.first else { return nil }
        var topViewController = window.rootViewController
        while let presentedViewController = topViewController?.presentedViewController { topViewController = presentedViewController }
        return topViewController
    }
}

extension AdsterUnity: MediationAdDelegate {
    public func onInterstitialAdLoaded(interstitialAd: any MediationInterstitialAd) {
        currentInterstitialAd = interstitialAd; interstitialImpressionSent = false
        UnitySendMessage("AdsterInterstitialAd", "HandleInterstitialAdLoaded", "Success")
    }
    public func onRewardedAdLoaded(rewardedAd: any MediationRewardedAd) {
        currentRewardedAd = rewardedAd; rewardedImpressionSent = false
        UnitySendMessage("AdsterRewardedAd", "HandleRewardedAdLoaded", "Success")
    }
    public func onRewardedInterstitialAdLoaded(rewardedInterstitialAd: any MediationRewardedInterstitialAd) {
        currentRewardedInterstitialAd = rewardedInterstitialAd; rewardedInterstitialImpressionSent = false
        UnitySendMessage("AdsterRewardedInterstitialAd", "HandleRewardedInterstitialAdLoaded", "Success")
    }
    public func onBannerAdLoaded(bannerAd: any MediationBannerAd) {
        currentBannerAd = bannerAd; bannerImpressionSent = false
        guard let view = bannerAd.view else { UnitySendMessage("AdsterBannerAd", "HandleBannerAdLoadFailed", "Banner view is null"); return }
        self.bannerView = view
        UnitySendMessage("AdsterBannerAd", "HandleBannerAdLoaded", "Success")
    }
    public func onAdFailedToLoad(error: AdError) {
        if interstitialLoader != nil && currentInterstitialAd == nil { UnitySendMessage("AdsterInterstitialAd", "HandleInterstitialAdLoadFailed", error.description!) }
        if rewardedLoader != nil && currentRewardedAd == nil { UnitySendMessage("AdsterRewardedAd", "HandleRewardedAdLoadFailed", error.description!) }
        if rewardedInterstitialLoader != nil && currentRewardedInterstitialAd == nil { UnitySendMessage("AdsterRewardedInterstitialAd", "HandleRewardedInterstitialAdLoadFailed", error.description!) }
        if bannerLoader != nil && currentBannerAd == nil { UnitySendMessage("AdsterBannerAd", "HandleBannerAdLoadFailed", error.description!) }
    }
    public func onNativeAdLoaded(nativeAd: any AdsFramework.MediationNativeAd) {}
    public func onCustomNativeAdLoaded(customNativeAd: any AdsFramework.MediationNativeCustomFormatAd) {}
}

extension AdsterUnity: MediationInterstitialAdEventDelegate {
    public func recordInterstitialClick() {
        UnitySendMessage("AdsterInterstitialAd", "HandleInterstitialAdClicked", "Success")
    }
    
    public func recordInterstitialImpression() {
        if interstitialImpressionSent { return }; interstitialImpressionSent = true; UnitySendMessage("AdsterInterstitialAd", "HandleInterstitialAdImpression", "Success")
    }
    
    public func ad(didFailToPresentFullScreenContentWithError error: AdError) { UnitySendMessage("AdsterInterstitialAd", "HandleInterstitialAdShowFailed", error.description!) }
    public func adWillPresentFullScreenContent() { UnitySendMessage("AdsterInterstitialAd", "HandleInterstitialAdWillShow", "Success") }
    public func adDidDismissFullScreenContent() { UnitySendMessage("AdsterInterstitialAd", "HandleInterstitialAdClosed", "Success"); currentInterstitialAd = nil; interstitialImpressionSent = false }
}

extension AdsterUnity: MediationRewardedAdEventDelegate {
    public func recordRewardedClick() {
        UnitySendMessage("AdsterRewardedAd", "HandleRewardedAdClicked", "Success")
    }
    
    public func recordRewardedImpression() {
        if rewardedImpressionSent { return }; rewardedImpressionSent = true; UnitySendMessage("AdsterRewardedAd", "HandleRewardedAdImpression", "Success")
    }
    
    public func didRewardUser(reward: AdsFramework.AdReward) {
        UnitySendMessage("AdsterRewardedAd", "HandleUserEarnedReward", reward.amount.stringValue)
    }
    
    public func didRewardUser() { UnitySendMessage("AdsterRewardedAd", "HandleUserEarnedReward", "100:coins") }
    public func didStartVideo() { UnitySendMessage("AdsterRewardedAd", "HandleRewardedAdVideoStarted", "Success") }
    public func didEndVideo() { UnitySendMessage("AdsterRewardedAd", "HandleRewardedAdVideoEnded", "Success") }
    public func ad(didFailToPresentFullScreenContentWithErrorRewarded error: AdError) { UnitySendMessage("AdsterRewardedAd", "HandleRewardedAdShowFailed", error.description!) }
    public func adWillPresentFullScreenContentRewarded() { UnitySendMessage("AdsterRewardedAd", "HandleRewardedAdWillShow", "Success") }
    public func adDidDismissFullScreenContentRewarded() { UnitySendMessage("AdsterRewardedAd", "HandleRewardedAdClosed", "Success"); currentRewardedAd = nil; rewardedImpressionSent = false }
}

extension AdsterUnity: MediationRewardedInterstitialAdEventDelegate {
    public func recordRewardedInterstitialClick() {
        UnitySendMessage("AdsterRewardedInterstitialAd", "HandleRewardedInterstitialAdClicked", "Success")
    }
    
    public func recordRewardedInterstitialImpression() {
        if rewardedInterstitialImpressionSent { return }
        rewardedInterstitialImpressionSent = true
        UnitySendMessage("AdsterRewardedInterstitialAd", "HandleRewardedInterstitialAdImpression", "Success")
    }
    
    public func didRewardUserRewardedInterstitial() { UnitySendMessage("AdsterRewardedInterstitialAd", "HandleRewardedInterstitialUserEarnedReward", "100:coins") }
    public func didStartVideoRewardedInterstitial() { UnitySendMessage("AdsterRewardedInterstitialAd", "HandleRewardedInterstitialAdVideoStarted", "Success") }
    public func didEndVideoRewardedInterstitial() { UnitySendMessage("AdsterRewardedInterstitialAd", "HandleRewardedInterstitialAdVideoEnded", "Success") }
    public func ad(didFailToPresentFullScreenContentWithErrorRewardedInterstitial error: AdError) { UnitySendMessage("AdsterRewardedInterstitialAd", "HandleRewardedInterstitialAdShowFailed", error.description!) }
    public func adWillPresentFullScreenContentRewardedInterstitial() { UnitySendMessage("AdsterRewardedInterstitialAd", "HandleRewardedInterstitialAdWillShow", "Success") }
    public func adDidDismissFullScreenContentRewardedInterstitial() { UnitySendMessage("AdsterRewardedInterstitialAd", "HandleRewardedInterstitialAdClosed", "Success"); currentRewardedInterstitialAd = nil; rewardedInterstitialImpressionSent = false }
}

extension AdsterUnity: MediationBannerAdEventDelegate {
    public func recordBannerClick() {
        UnitySendMessage("AdsterBannerAd", "HandleBannerAdClicked", "Success")
    }
    
    public func recordBannerImpression() {
        if bannerImpressionSent { return }; bannerImpressionSent = true; UnitySendMessage("AdsterBannerAd", "HandleBannerAdImpression", "Success")
    }
}

@_cdecl("print_hello_swift") public func print_hello_swift() { AdsterUnity.shared.printHelloSwift() }
@_cdecl("initilalize_sdk") public func initilalize_sdk() { AdsterUnity.shared.initializeSDK() }
@_cdecl("load_interstitial_ad") public func load_interstitial_ad(_ placementKey: UnsafePointer<CChar>) { let s = String(cString: placementKey); AdsterUnity.shared.loadInterstitialAd(s) }
@_cdecl("show_interstitial_ad") public func show_interstitial_ad() { AdsterUnity.shared.showInterstitialAd() }
@_cdecl("load_rewarded_ad") public func load_rewarded_ad(_ placementKey: UnsafePointer<CChar>) { let s = String(cString: placementKey); AdsterUnity.shared.loadRewardedAd(s) }
@_cdecl("show_rewarded_ad") public func show_rewarded_ad() { AdsterUnity.shared.showRewardedAd() }
@_cdecl("load_rewarded_interstitial_ad") public func load_rewarded_interstitial_ad(_ placementKey: UnsafePointer<CChar>) { let s = String(cString: placementKey); AdsterUnity.shared.loadRewardedInterstitialAd(s) }
@_cdecl("show_rewarded_interstitial_ad") public func show_rewarded_interstitial_ad() { AdsterUnity.shared.showRewardedInterstitialAd() }
@_cdecl("load_banner_ad") public func load_banner_ad(_ placementKey: UnsafePointer<CChar>) { let s = String(cString: placementKey); AdsterUnity.shared.loadBannerAd(s) }
@_cdecl("show_banner_ad") public func show_banner_ad(_ placement: Int32) { AdsterUnity.shared.showBannerAd(Int(placement)) }
@_cdecl("hide_banner_ad") public func hide_banner_ad() { AdsterUnity.shared.hideBannerAd() }
@_cdecl("destroy_banner_ad") public func destroy_banner_ad() { AdsterUnity.shared.destroyBannerAd() }
