//
//  AirbridgeReactNative.swift
//  AirbridgeReactNative
//
//  Created by WOF on 7/8/24.
//

import OSLog
import Airbridge

@objc(AirbridgeReactNative_Swift)
public class AirbridgeReactNative: NSObject {
    
    @objc
    private static var airbridgeJSON: [AnyHashable: Any]? = nil

    private static var isHandleAirbridgeDeeplinkOnly: Bool = false
    
    private static var subWrapperSDKDevelopmentPlatform: String? = nil
    private static var subWrapperSDKAttributes: [String: String]? = nil

    /// Initialize Airbridge SDK.
    /// - Parameter name: Name of Airbridge app that set on dashboard.
    /// - Parameter token: App token of Airbridge app that displayed on dashboard.
    @objc
    public static func initializeSDK(
        name: String,
        token: String
    ) {
        airbridgeJSON = AirbridgeJSON.loadAirbridgeJSON()
        
        setExtraOptions(airbridgeJSON: airbridgeJSON)

        Airbridge.initializeSDK(
            option: AirbridgeOptionBuilder(name: name, token: token)
                .setAirbridgeJSON(airbridgeJSON)
                .setSDKDevelopmentPlatform(getSDKDevelopmentPlatform())
                .setSDKAttributes(getWrapperSDKAttributes())
                .setSDKWrapperOption(getSDKWrapperOption())
                .setOnAttributionReceived { attribution in
                    AttributionInteractor.onAttributionReceived(attribution)
                }
                .build()
        )
        Airbridge.handleDeferredDeeplink { url in
            guard let url else { return }
            DeeplinkInteractor.onDeeplinkReceived(url)
        } onFailure: { error in
            Logger.debug("Failure on Airbridge.handleDeferredDeeplink: error={\(error.localizedDescription)}")
        }
    }
    
    /// Tracks app behavior through deeplink.
    /// - Parameter url: URL of deeplink (Scheme Deeplink).
    /// - Note: Whenever `application:openURL:options:` is called,
    /// developer must also call this method.
    @objc
    public static func trackDeeplink(url: URL) {
        Airbridge.trackDeeplink(url: url)
        let handled = Airbridge.handleDeeplink(url: url) { url in
            DeeplinkInteractor.onDeeplinkReceived(url)
        } onFailure: { error in
            Logger.debug("Failure on Airbridge.handleDeeplink: error={\(error.localizedDescription)}")
        }
        guard !(handled || isHandleAirbridgeDeeplinkOnly) else { return }
        DeeplinkInteractor.onDeeplinkReceived(url)
    }
    
    /// Tracks app behavior through deeplink.
    /// - Parameter userActivity: UserActivity of deeplink (Universal Links).
    /// - Note: Per every `application:continueUserActivity:restorationHandler:` call,
    /// developer must call `trackDeeplink`.
    @objc
    public static func trackDeeplink(userActivity: NSUserActivity) {
        Airbridge.trackDeeplink(userActivity: userActivity)
        let handled = Airbridge.handleDeeplink(userActivity: userActivity) { url in
            DeeplinkInteractor.onDeeplinkReceived(url)
        }
        guard !(handled || isHandleAirbridgeDeeplinkOnly), let url = userActivity.webpageURL else { return }
        DeeplinkInteractor.onDeeplinkReceived(url)
    }

    @objc
    private static func setExtraOptions(airbridgeJSON: [AnyHashable: Any]?) {
        guard let airbridgeJSON else { return }
        if let isHandleAirbridgeDeeplinkOnly = airbridgeJSON["isHandleAirbridgeDeeplinkOnly"] as? Bool {
            AirbridgeReactNative.isHandleAirbridgeDeeplinkOnly = isHandleAirbridgeDeeplinkOnly
        }
    }
    
    private static func getSDKDevelopmentPlatform() -> String {
        return subWrapperSDKDevelopmentPlatform ?? "react_native"
    }
    
    private static func getWrapperSDKAttributes() -> [String: String] {
        return getSDKVersionAttributes()
            .merging(subWrapperSDKAttributes ?? [:]) { _, new in new }
    }
    
    private static func getSDKWrapperOption() -> [String: Any] {
        return [
            "isHandleAirbridgeDeeplinkOnly" : isHandleAirbridgeDeeplinkOnly
        ]
    }
    
    @objc
    private static func setSubWrapperSDK(
        developmentPlatform: String,
        sdkAttributes: [String : String]
    ) {
        subWrapperSDKDevelopmentPlatform = developmentPlatform
        subWrapperSDKAttributes = sdkAttributes
    }
}

func getSDKVersionAttributes() -> [String: String] {
    guard
       let path = Bundle.main.path(forResource: "LibraryInfo", ofType: "json"),
       let data = try? Data(contentsOf: URL(fileURLWithPath: path))
    else { return [:] }
    
    if 
        let raw = try? JSONSerialization.jsonObject(with: data),
        let json = raw as? [String: Any] {
            return json.compactMapValues { $0 as? String }
    }
    
    Logger.warning("File LibraryInfo.json is not in json format")
    return [:]
}
