
import Flutter
import UIKit
import GravityEngineSDK

public class GravityEnginePlugin: NSObject, FlutterPlugin {

    // Method names
    private static let METHOD_INITIALIZE = "initialize"
    private static let METHOD_TRACK = "track"
    private static let METHOD_TRACK_PAY = "trackPay"

    // Arguments
    private static let ARG_ACCESS_TOKEN = "accessToken"
    private static let ARG_DEBUG = "debug"
    private static let ARG_CLIENT_ID = "clientId"
    private static let ARG_CHANNEL = "channel"

    //ios>>>
    private static let ARG_APPID = "appId"
    //<<<ios

    private static let ARG_EVENT_ID = "eventId"
    private static let ARG_EVENT_PARAMS = "eventParams"

    private static let ARG_ORDER_NO = "orderNo"
    private static let ARG_AMOUNT = "amount"
    private static let ARG_CURRENCY = "currency"
    private static let ARG_PAY_TYPE = "payType"
    private static let ARG_ITEM_NAME = "itemName"

    public static var gravityEngineSDK: GravityEngineSDK?
    private static var isInitialized = false

    public static func register(with registrar: FlutterPluginRegistrar) {
        let channel = FlutterMethodChannel(name: "gravity_engine", binaryMessenger: registrar.messenger())
        let instance = GravityEnginePlugin()
        registrar.addMethodCallDelegate(instance, channel: channel)
    }

    public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
        switch call.method {
        case GravityEnginePlugin.METHOD_INITIALIZE:
            DebugPrint("GravityEnginePlugin.METHOD_INITIALIZE = \(call.method)");
            IDFAManager.getIDFA(call: call, result: result)
        case GravityEnginePlugin.METHOD_TRACK:
            DebugPrint("GravityEnginePlugin.METHOD_TRACK = \(call.method)");
            GravityEnginePlugin.track(call: call, result: result)
        case GravityEnginePlugin.METHOD_TRACK_PAY:
            DebugPrint("GravityEnginePlugin.METHOD_TRACK_PAY = \(call.method)");
            GravityEnginePlugin.trackPay(call: call, result: result)
        default:
            result(FlutterMethodNotImplemented)
        }
    }

    //init
    public static func initialize(call: FlutterMethodCall, result: @escaping FlutterResult, idfa: String) {
        guard let args = call.arguments as? [String: Any],
              let accessToken = args[GravityEnginePlugin.ARG_ACCESS_TOKEN] as? String,
              let appid = args[GravityEnginePlugin.ARG_APPID] as? String,
              let debug = args[GravityEnginePlugin.ARG_DEBUG] as? Bool,
              let channel = args[GravityEnginePlugin.ARG_CHANNEL] as? String else {
            result(FlutterError(code: "-1", message: "Missing required arguments", details: nil))
            return
        }

        //配置引力引擎
        let config = GEConfig();
        config.appid = appid;
        config.accessToken = accessToken;
        if debug{
            config.debugMode = GravityEngineDebugMode.on;
        }else{
            config.debugMode = [];
        }
        GravityEngineSDK.start(with: config);
        let instance = GravityEngineSDK.sharedInstance(withAppid: config.appid);

        //全局引力引擎实例
        gravityEngineSDK = instance

        // 开启自动采集
        gravityEngineSDK?.enableAutoTrack(GravityEngineAutoTrackEventType.eventTypeAll);

        //获取idfv
        var idfv = ""
        if let idfVendor = UIDevice.current.identifierForVendor {
            idfv = idfVendor.uuidString
            DebugPrint("引力引擎 IDFV == \(idfv)")
        } else {
            DebugPrint("引力引擎 无法获取 IDFV")
        }
        
        //获取当前版本号
        var appVersionName = 1
        if let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
            appVersionName = Int(appVersion) ?? 1
        }
        //自动归因
        let enableAsa = true
        //其他参数
        let userCaid1MD5 = ""
        let userCaid2MD5 = ""
        let enableSyncAttribution = true

        //初始化sdk
        gravityEngineSDK?.initializeGravityEngine(withClientId: idfv, withUserName: idfv, withVersion: Int32(appVersionName), withAsaEnable:enableAsa, withIdfa:idfa, withIdfv:idfv, withCaid1:userCaid1MD5, withCaid2:userCaid2MD5, withSyncAttribution:enableSyncAttribution, withSuccessCallback: { response in
//            DebugPrint("gravity engine initialize success, response is ", response);
            self.isInitialized = true
            result(response)
        }, withErrorCallback: { error in
//            DebugPrint("gravity engine initialize failed, and error is", error);
            result(FlutterError(code: "-1", message: "Initialization failed", details: error.localizedDescription))
        });

        // 获取用户信息
        //        instance?.queryUserInfo(successCallback: { response in
        ////            print("user info \(response)")
        //        }, withErrorCallback: { error in
        ////            print("get user info error \(error)")
        //        })

        //设置公共属性
        var superProperties: [String : Any] = ["channel":channel]
        gravityEngineSDK?.setSuperProperties(superProperties)

    }

    //event
    private static func track(call: FlutterMethodCall, result: @escaping FlutterResult) {
        guard let args = call.arguments as? [String: Any],
              let eventId = args[GravityEnginePlugin.ARG_EVENT_ID] as? String else {
            result(FlutterError(code: "-1", message: "Missing eventId", details: nil))
            return
        }
        guard isInitialized, let sdk = gravityEngineSDK else {
            result(FlutterError(code: "-1", message: "SDK not initialized", details: nil))
            return
        }
        let eventParams = args[GravityEnginePlugin.ARG_EVENT_PARAMS] as? [String: Any]
        sdk.track(eventId, properties: eventParams)
        result(nil)
    }

    //pay
    private static func trackPay(call: FlutterMethodCall, result: @escaping FlutterResult) {
        guard let args = call.arguments as? [String: Any],
              let orderNo = args[GravityEnginePlugin.ARG_ORDER_NO] as? String,
              let amount = args[GravityEnginePlugin.ARG_AMOUNT] as? Int,
              let currency = args[GravityEnginePlugin.ARG_CURRENCY] as? String,
              let itemName = args[GravityEnginePlugin.ARG_ITEM_NAME] as? String,
              let payType = args[GravityEnginePlugin.ARG_PAY_TYPE] as? String else {
            result(FlutterError(code: "-1", message: "Missing required arguments", details: nil))
            return
        }
        guard isInitialized, let sdk = gravityEngineSDK else {
            result(FlutterError(code: "-1", message: "SDK not initialized", details: nil))
            return
        }
        sdk.trackPayEvent(withAmount: Int32(amount), withPayType: payType, withOrderId: orderNo, withPayReason: itemName, withPayMethod: currency)
        result(nil)
    }

}
