#import "SEPluginLibrary.h"
#include <Foundation/Foundation.h>
#import <SolarEngineSDK/SolarEngineSDK.h>
#import <SolarEngineSDK/SERemoteConfigManager.h>
#if  __has_include(<SolarEngineSDK/SESDKForCN.h>)
#import <SolarEngineSDK/SESDKForCN.h>
#endif
#if  __has_include(<SolarEngineSDK/SESDKForUS.h>)
#import <SolarEngineSDK/SESDKForUS.h>
#endif
@interface SEWrapperManager : NSObject

@property (nonatomic,copy)NSString *sub_lib_version;
@property (nonatomic,copy)NSString *sdk_type;

+ (SEWrapperManager *)sharedInstance;

@end

@implementation SEWrapperManager

+ (SEWrapperManager *)sharedInstance {
    static SEWrapperManager * instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] init];
    });
    return instance;
}
@end

BOOL SELogEnabled =NO;
static void SELog(NSString *format, ...) {
    if (!SELogEnabled) return;
    
    va_list args;
    va_start(args, format);
    NSString *logString = [[NSString alloc] initWithFormat:format arguments:args];
    va_end(args);
    
    NSLog(@"[SE.CoronaiOSSDK] %@", logString);
}

static void SELogError(NSString *format, ...) {
    
    va_list args;
    va_start(args, format);
    NSString *logString = [[NSString alloc] initWithFormat:format arguments:args];
    va_end(args);
    
    NSLog(@"[SE.CoronaiOSSDK] %@", logString);
}
static NSDictionary* taJsonToDictionary(const char *json) {
    if (!json) return @{};
    NSString *jsonStr = [NSString stringWithUTF8String:json];
    if (!jsonStr) return @{};
    NSData *data = [jsonStr dataUsingEncoding:NSUTF8StringEncoding];
    return [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil] ?: @{};
}
static NSString * taDictionaryToJson(NSDictionary * params) {
    NSString *jsonStr = nil;
    if (params != nil && [params isKindOfClass:[NSDictionary class]]) {
        NSData *jsonData = [NSJSONSerialization dataWithJSONObject:params options:NSJSONWritingPrettyPrinted error:NULL];
        jsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    }
    return jsonStr?:@"";
}
// 公共转换函数：将任意 Objective-C 对象转换为 NSString
static NSString *convertToNSString(id data) {
    if (!data || data == [NSNull null]) {
        return @"";
    }
    
    // 1. 处理 NSDictionary / NSArray -> JSON 字符串
    if ([data isKindOfClass:[NSDictionary class]] || [data isKindOfClass:[NSArray class]]) {
        NSError *error = nil;
        NSData *jsonData = [NSJSONSerialization dataWithJSONObject:data options:0 error:&error];
        if (jsonData && !error) {
            return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
        }
    }
    
    // 2. 处理 NSNumber / __NSCFBoolean
    if ([data isKindOfClass:[NSNumber class]]) {
        NSString *className = NSStringFromClass([data class]);
        if ([className isEqualToString:@"__NSCFBoolean"]) {
            return [(NSNumber *)data boolValue] ? @"true" : @"false";
        } else {
            return [(NSNumber *)data stringValue];
        }
    }
    
    // 3. 处理 NSString
    if ([data isKindOfClass:[NSString class]]) {
        return (NSString *)data;
    }
    
    // 4. 其他类型 → 调用 description
    return [data description];
}
static id seTrimValue(id __nullable value){
    
    if (!value || [value isEqual:[NSNull null]]) {
        return nil;
    }
    
    return value;
}

static SEConfig* initSEConfig( NSDictionary *configDic) {
    SEConfig *seConfig = [[SEConfig alloc] init];
    seConfig.logEnabled=[[configDic objectForKey:@"logEnabled"]boolValue];
    NSLog(@"[SEPluginLibrary] logEnabled(raw): %@, logEnabled(BOOL): %d",
          [configDic objectForKey:@"logEnabled"],
          seConfig.logEnabled);
    SELogEnabled=seConfig.logEnabled;
    seConfig.isDebugModel=[[configDic objectForKey:@"isDebugModel"] boolValue];
    seConfig.isGDPRArea=[[configDic objectForKey:@"isGDPRArea"] boolValue];
    seConfig.setCoppaEnabled=[[configDic objectForKey:@"isCoppaEnabled"]boolValue];
    seConfig.setKidsAppEnabled=[[configDic objectForKey:@"isKidsAppEnabled"]boolValue];
    seConfig.enable2GReporting=[[configDic objectForKey:@"enable2GReporting"]boolValue];
    
    seConfig.attAuthorizationWaitingInterval=[[configDic objectForKey:@"attAuthorizationWaitingInterval"] intValue];
    seConfig.enableDeferredDeeplink=[[configDic objectForKey:@"enableDeferredDeeplink"] boolValue];
#if  __has_include(<SolarEngineSDK/SESDKForCN.h>)
    seConfig.caid=[configDic objectForKey:@"caid"];
#endif
#if  __has_include(<SolarEngineSDK/SESDKForUS.h>)
    if (seDict[@"odmInfoEnable"]) {
        config.enableODMInfo = [configDic[@"odmInfoEnable"] boolValue];
    }
#endif
    
    NSDictionary *rcDict = [configDic objectForKey:@"remoteConfig"];
    if ([rcDict isKindOfClass:[NSDictionary class]]) {
        SERemoteConfig *remoteConfig = [[SERemoteConfig alloc] init];
        remoteConfig.enable = [rcDict[@"enable"] boolValue];
        remoteConfig.logEnabled = seConfig.logEnabled;
        
        remoteConfig.mergeType = (SERCMergeType)[rcDict[@"mergeType"] integerValue];
        
        remoteConfig.customIDProperties = rcDict[@"customIDProperties"];
        remoteConfig.customIDUserProperties = rcDict[@"customIDUserProperties"];
        remoteConfig.customIDEventProperties = rcDict[@"customIDEventProperties"];
        
        seConfig.remoteConfig = remoteConfig;
    }
    
    
    NSDictionary *customDomainDict = [configDic objectForKey:@"customDomain"];
    
    if ([customDomainDict isKindOfClass:[NSDictionary class]]) {
        
        SECustomDomain *customDomain = [[SECustomDomain alloc] init];
        customDomain.enable             = [customDomainDict[@"enable"] boolValue];
        customDomain.receiverDomain     = customDomainDict[@"receiverDomain"];
        customDomain.ruleDomain         = customDomainDict[@"ruleDomain"];
        customDomain.ruleTcpHost        = customDomainDict[@"tcpRuleHost"];
        customDomain.receiverTcpHost    = customDomainDict[@"tcpReceiverHost"];
        customDomain.gatewayTcpHost     = customDomainDict[@"tcpGatewayHost"];
        seConfig.customDomain = customDomain;
    }
    return seConfig;
}


#pragma mark -APISTART--
int SEPluginLibrary::preinit(lua_State *L) {
    const char* appKey = lua_tostring(L, 1);
    if (appKey) {
        SELog(@"[SEPluginLibrary] preInitSdk called with appKey: %s", appKey);
        [[SolarEngineSDK sharedInstance] preInitWithAppKey:[NSString stringWithUTF8String:appKey]];
    }
    return 0;
}

int SEPluginLibrary::initSdk(lua_State *L) {
    const char* configJson = lua_tostring(L, 1);
    const char* propertiesJson = lua_tostring(L, 2);
    
    NSDictionary *configDic = taJsonToDictionary(configJson);
    NSDictionary *propertiesDic = taJsonToDictionary(propertiesJson);
    
    NSString*appKey=[configDic objectForKey:@"appKey"];
    
    if (appKey) {
        SELog(@"[SEPluginLibrary] initSdk called with appKey: %@", appKey);
        
        NSString *sub_lib_version = propertiesDic[@"subLibVersion"];
        if ([sub_lib_version isKindOfClass:[NSString class]]) {
            [SEWrapperManager sharedInstance].sub_lib_version = sub_lib_version;
        }
        
        NSString *sdk_type = propertiesDic[@"sdkType"];
        if ([sdk_type isKindOfClass:[NSString class]]) {
            [SEWrapperManager sharedInstance].sdk_type = sdk_type;
        }
        
        
        [[SolarEngineSDK sharedInstance] startWithAppKey:appKey config:initSEConfig( configDic)];
    }
    return 0;
}

int SEPluginLibrary::getDistinctId(lua_State* L) {
    @autoreleasepool {
        NSString *distinctId =  [[SolarEngineSDK sharedInstance] getDistinctId];
        SELog(@"[SEPluginLibrary] getAccountId called with accountId: %@", distinctId);
        
        if (distinctId.length > 0)
            lua_pushstring(L, [distinctId UTF8String]);
        else
            lua_pushstring(L, "");
        return 1;
    }
}
int SEPluginLibrary::getAccountId(lua_State* L) {
    @autoreleasepool {
        NSString *accountId =  [[SolarEngineSDK sharedInstance] accountID];
        SELog(@"[SEPluginLibrary] getAccountId called with accountId: %@", accountId);
        if (accountId.length > 0)
            lua_pushstring(L, [accountId UTF8String]);
        else
            lua_pushstring(L, "");
        return 1;
    }
}
int SEPluginLibrary::getVisitorId(lua_State* L) {
    @autoreleasepool {
        NSString *visitorId =  [[SolarEngineSDK sharedInstance] visitorID];
        if (visitorId.length > 0)
            lua_pushstring(L, [visitorId UTF8String]);
        else
            lua_pushstring(L, "");
        return 1;
    }
}
int SEPluginLibrary::setVisitorId(lua_State* L) {
    @autoreleasepool {
        const char *visitorId = lua_tostring(L, 1);
        if (visitorId) {
            [[SolarEngineSDK sharedInstance] setVisitorID:[NSString stringWithUTF8String:visitorId]];
        }
        return 0;
    }
}


int SEPluginLibrary::login(lua_State* L) {
    @autoreleasepool {
        const char *accountId = lua_tostring(L, 1);
        if (accountId) {
            SELog(@"[SEPluginLibrary] login called with accountId: %s", accountId);
            [[SolarEngineSDK sharedInstance] loginWithAccountID:[NSString stringWithUTF8String:accountId]];
        }
        return 0;
    }
}

int SEPluginLibrary::logout(lua_State* L) {
    @autoreleasepool {
        SELog(@"[SEPluginLibrary] logout called");
        [[SolarEngineSDK sharedInstance] logout];
        return 0;
    }
}
int SEPluginLibrary::setPresetEvent(lua_State* L) {
    @autoreleasepool {
        NSInteger eventType = lua_tointeger(L, 1);
        const char *json = lua_tostring(L, 2);
        NSDictionary *dic = taJsonToDictionary(json);
        
        [[SolarEngineSDK sharedInstance] setPresetEvent:(SEPresetEventType)eventType withProperties:dic];
        
        return 0;
    }
}
int SEPluginLibrary::setSuperProperties(lua_State* L) {
    @autoreleasepool {
        const char *json = lua_tostring(L, 1);
        NSDictionary *dic = taJsonToDictionary(json);
        [[SolarEngineSDK sharedInstance] setSuperProperties:dic];
        return 0;
    }
}
int SEPluginLibrary::unsetSuperProperty(lua_State* L) {
    @autoreleasepool {
        const char *propertyName = lua_tostring(L, 1);
        if (propertyName) {
            [[SolarEngineSDK sharedInstance] unsetSuperProperty:[NSString stringWithUTF8String:propertyName]];
        }
        return 0;
    }
}
int SEPluginLibrary::clearSuperProperties(lua_State* L) {
    @autoreleasepool {
        [[SolarEngineSDK sharedInstance] clearSuperProperties];
        return 0;
    }
}
int SEPluginLibrary::getPresetProperties(lua_State* L) {
    @autoreleasepool {
        NSDictionary *dic = [[SolarEngineSDK sharedInstance] getPresetProperties];
        if (dic) {
            lua_pushstring(L, [taDictionaryToJson(dic) UTF8String]);
        } else {
            lua_pushstring(L, "");
        }
        return 1;
    }
}
#pragma mark -USER--
int SEPluginLibrary::userInit(lua_State* L) {
    @autoreleasepool {
        const char *json = lua_tostring(L, 1);
        NSDictionary *dic = taJsonToDictionary(json);
        [[SolarEngineSDK sharedInstance] userInit:dic];
        return 0;
    }
}
int SEPluginLibrary::userUpdate(lua_State* L) {
    @autoreleasepool {
        const char *json = lua_tostring(L, 1);
        NSDictionary *dic = taJsonToDictionary(json);
        [[SolarEngineSDK sharedInstance] userUpdate:dic];
        
        return 0;
    }
}
int SEPluginLibrary::userUnset(lua_State* L) {
    @autoreleasepool {
        const char *keys = lua_tostring(L, 1);
        NSString *_keys = [NSString stringWithUTF8String:keys];
        
        NSData *data = [_keys dataUsingEncoding:NSUTF8StringEncoding];
        
        NSError *error = nil;
        NSArray *array = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
        
        if (error) {
            NSString *msg = [NSString stringWithFormat:@"%@ is not an invalid JSON data",_keys];
            SELog(@"userUnset, error :%@", msg);
            
        }
        
        if (![array isKindOfClass:NSArray.class]) {
            NSString *msg = [NSString stringWithFormat:@"%@ is not an array",_keys];
            SELog(@"userUnset, error :%@", msg);
            
        }
        [[SolarEngineSDK sharedInstance] userUnset:array];
        
        return 0;
    }
}
int SEPluginLibrary::userAppend(lua_State* L) {
    @autoreleasepool {
        
        const char *json = lua_tostring(L, 1);
        NSDictionary *dic = taJsonToDictionary(json);
        [[SolarEngineSDK sharedInstance] userAppend:dic];
        
        return 0;
    }
}
int SEPluginLibrary::userAdd(lua_State* L) {
    @autoreleasepool {
        const char *json = lua_tostring(L, 1);
        NSDictionary *dic = taJsonToDictionary(json);
        [[SolarEngineSDK sharedInstance] userAdd:dic];
        
        return 0;
    }
}
int SEPluginLibrary::userDelete(lua_State* L) {
    @autoreleasepool {
        NSInteger  type = lua_tointeger(L, 1);
        [[SolarEngineSDK sharedInstance] userDelete:(SEUserDeleteType)type];
        
        return 0;
    }
}

#pragma mark-EVENT


int SEPluginLibrary::trackPurchase(lua_State* L) {
    @autoreleasepool {
        const char *json = lua_tostring(L, 1);
        NSDictionary *dict = taJsonToDictionary(json);
        SEIAPEventAttribute *attribute = [[SEIAPEventAttribute alloc] init];
        
        attribute.productID    = seTrimValue([dict objectForKey:@"productId"]);
        attribute.productName  = seTrimValue([dict objectForKey:@"productName"]);
        attribute.productCount = [seTrimValue([dict objectForKey:@"productCount"]) integerValue];
        attribute.orderId      = seTrimValue([dict objectForKey:@"orderId"]);
        attribute.payAmount    = [seTrimValue([dict objectForKey:@"payAmount"]) doubleValue];
        attribute.currencyType = seTrimValue([dict objectForKey:@"currencyType"]);
        attribute.payType      = seTrimValue([dict objectForKey:@"payType"]);
        attribute.payStatus    = (SolarEngineIAPStatus)[seTrimValue([dict objectForKey:@"payStatus"]) integerValue];
        attribute.failReason   = seTrimValue([dict objectForKey:@"failReason"]);
        attribute.customProperties = seTrimValue([dict objectForKey:@"customProperties"]);
        [[SolarEngineSDK sharedInstance] trackIAPWithAttributes:attribute];
        return 0;
        
        
    }
}


int SEPluginLibrary::trackAdImpression(lua_State* L) {
    @autoreleasepool {
        const char *json = lua_tostring(L, 1);
        NSDictionary *dict = taJsonToDictionary(json);
        SEAdImpressionEventAttribute *attribute = [[SEAdImpressionEventAttribute alloc] init];
        attribute.adType              = (SolarEngineAdType)[seTrimValue( [dict objectForKey:@"adType"])  integerValue];
        attribute.adNetworkPlatform   = seTrimValue([dict objectForKey:@"adPlatform"]);
        attribute.mediationPlatform   = seTrimValue([dict objectForKey:@"mediationPlatform"]);
        attribute.adNetworkAppID      = seTrimValue([dict objectForKey:@"adAppId"]);
        attribute.adNetworkPlacementID= seTrimValue([dict objectForKey:@"adId"]);
        attribute.ecpm                = [seTrimValue([dict objectForKey:@"adECPM"]) doubleValue];
        attribute.currency            = seTrimValue([dict objectForKey:@"currencyType"]);
        attribute.rendered            = [seTrimValue([dict objectForKey:@"isRendered"]) boolValue];
        attribute.customProperties   =seTrimValue ([dict objectForKey:@"customProperties"]);
        [[SolarEngineSDK sharedInstance] trackAdImpressionWithAttributes:attribute];
        
        return 0;
    }
    
}

int SEPluginLibrary::trackAdClick(lua_State* L) {
    @autoreleasepool {
        const char *json = lua_tostring(L, 1);
        NSDictionary *dict = taJsonToDictionary(json);
        SEAdClickEventAttribute *attribute = [[SEAdClickEventAttribute alloc] init];
        attribute.adType              = (SolarEngineAdType)[seTrimValue( [dict objectForKey:@"adType"])  integerValue];
        attribute.adNetworkPlatform   = seTrimValue([dict objectForKey:@"adNetworkPlatform"]);
        attribute.adNetworkPlacementID             = seTrimValue([dict objectForKey:@"adNetworkPlacementId"]);
        
        attribute.mediationPlatform   = seTrimValue([dict objectForKey:@"mediationPlatform"]);
        attribute.customProperties   =seTrimValue ([dict objectForKey:@"customProperties"]);
        
        [[SolarEngineSDK sharedInstance] trackAdClickWithAttributes:attribute];
        return 0;
        
    }
}
int SEPluginLibrary::trackOrder(lua_State* L) {
    @autoreleasepool {
        const char *json = lua_tostring(L, 1);
        NSDictionary *dict = taJsonToDictionary(json);
        SEOrderEventAttribute *attribute = [[SEOrderEventAttribute alloc] init];
        attribute.orderID       = seTrimValue([dict objectForKey:@"orderId"]);
        attribute.payAmount    = [seTrimValue([dict objectForKey:@"payAmount"]) doubleValue];
        attribute.currencyType  = seTrimValue([dict objectForKey:@"currencyType"]);
        attribute.payType       = seTrimValue([dict objectForKey:@"payType"]);
        attribute.status        = seTrimValue([dict objectForKey:@"status"]);
        attribute.customProperties   =seTrimValue ([dict objectForKey:@"customProperties"]);
        [[SolarEngineSDK sharedInstance] trackOrderWithAttributes:attribute];
        return 0;
        
    }
}


int SEPluginLibrary:: trackRegister(lua_State* L) {
    @autoreleasepool {
        const char *json = lua_tostring(L, 1);
        NSDictionary *dict = taJsonToDictionary(json);
        SERegisterEventAttribute *attribute = [[SERegisterEventAttribute alloc] init];
        attribute.registerType   = seTrimValue([dict objectForKey:@"registerType"]);
        attribute.registerStatus = seTrimValue([dict objectForKey:@"registerStatus"]);
        attribute.customProperties   =seTrimValue ([ dict objectForKey:@"customProperties"]);
        [[SolarEngineSDK sharedInstance] trackRegisterWithAttributes:attribute];
        return 0;
    }
}

int SEPluginLibrary::trackLogin(lua_State* L) {
    @autoreleasepool {
        const char *json = lua_tostring(L, 1);
        NSDictionary *dict = taJsonToDictionary(json);
        SELoginEventAttribute *attribute = [[SELoginEventAttribute alloc] init];
        attribute.loginType    = seTrimValue([dict objectForKey:@"loginType"]);
        attribute.loginStatus  = seTrimValue([dict objectForKey:@"loginStatus"]);
        attribute.customProperties   =seTrimValue ( [dict objectForKey:@"customProperties"]);
        [[SolarEngineSDK sharedInstance] trackLoginWithAttributes:attribute];
        return 0;
    }
}



int SEPluginLibrary::trackAttribution(lua_State* L) {
    @autoreleasepool {
        const char *json = lua_tostring(L, 1);
        NSDictionary *dict = taJsonToDictionary(json);
        SEAppAttrEventAttribute *attribute = [[SEAppAttrEventAttribute alloc] init];
        attribute.adNetwork           = seTrimValue([dict objectForKey:@"adNetwork"]);
        attribute.subChannel          = seTrimValue([dict objectForKey:@"subChannel"]);
        attribute.adAccountID         = seTrimValue([dict objectForKey:@"adAccountId"]);
        attribute.adAccountName       = seTrimValue([dict objectForKey:@"adAccountName"]);
        attribute.adCampaignID        = seTrimValue([dict objectForKey:@"adCampaignId"]);
        attribute.adCampaignName      = seTrimValue([dict objectForKey:@"adCampaignName"]);
        attribute.adOfferID           = seTrimValue([dict objectForKey:@"adOfferId"]);
        attribute.adOfferName         = seTrimValue([dict objectForKey:@"adOfferName"]);
        attribute.adCreativeID        = seTrimValue([dict objectForKey:@"adCreativeId"]);
        attribute.adCreativeName      = seTrimValue([dict objectForKey:@"adCreativeName"]);
        attribute.attributionPlatform = seTrimValue([dict objectForKey:@"attributionPlatform"]);
        attribute.customProperties   =seTrimValue ([dict objectForKey:@"customProperties"]);
        [[SolarEngineSDK sharedInstance] trackAppAttrWithAttributes:attribute];
        return 0;
        
        
    }
}
int SEPluginLibrary::eventStart(lua_State* L) {
    @autoreleasepool {
        const char *eventname = lua_tostring(L, 1);
        [[SolarEngineSDK sharedInstance] eventStart:[NSString stringWithUTF8String:eventname]];
        return 0;
    }
}
int SEPluginLibrary::eventFinish(lua_State* L) {
    @autoreleasepool {
        const char *eventname = lua_tostring(L, 1);
        const char *json = lua_tostring(L, 2);
        NSDictionary *dict = taJsonToDictionary(json);
        [[SolarEngineSDK sharedInstance]  eventFinish:[NSString stringWithUTF8String:eventname] properties:dict];
        return 0;
    }
}
int SEPluginLibrary::track(lua_State *L) {
    @autoreleasepool {
        
        int argc = lua_gettop(L);
        
        // 第1个参数：事件名（必填）
        if (argc < 1 || !lua_isstring(L, 1)) {
            luaL_error(L, "track(eventName, [json], [extra]) requires at least 1 string parameter");
            return 0;
        }
        const char *eventNameC = lua_tostring(L, 1);
        NSString *eventName = [NSString stringWithUTF8String:eventNameC];
        
        NSDictionary *customdic = nil;
        if (argc >= 2 && !lua_isnoneornil(L, 2)) {
            const char *jsonC = lua_tostring(L, 2);
            if (jsonC) {
                customdic = taJsonToDictionary(jsonC);
            }
        }
        
        NSDictionary *predic = nil;
        if (argc >= 3 && !lua_isnoneornil(L, 3)) {
            const char *prestr = lua_tostring(L, 3);
            if (prestr) {
                predic = taJsonToDictionary(prestr);
            }
        }
        
        
        
        [[SolarEngineSDK sharedInstance] track:eventName  withCustomProperties:customdic withPresetProperties:predic];
        return 0;
    }
}

int SEPluginLibrary::trackAppReEngagement(lua_State* L) {
    @autoreleasepool {
        const char *json = lua_tostring(L, 1);
        NSDictionary *dict = taJsonToDictionary(json);
        
        [[SolarEngineSDK sharedInstance] trackAppReEngagement:dict];
        return 0;
    }
}
int SEPluginLibrary::trackFirstEvent(lua_State* L) {
    @autoreleasepool {
        const  char *eventname = lua_tostring(L, 1);
        const char*firstcheckid = lua_tostring(L, 2);
        const char *json = lua_tostring(L, 3);
        NSDictionary *dict = taJsonToDictionary(json);
        NSString *eventName = [NSString stringWithUTF8String:eventname];
        NSString *firstCheckId = [NSString stringWithUTF8String:firstcheckid];
        if ([eventName isEqualToString:@"_appReg"]) {
            SERegisterEventAttribute *attribute = [[SERegisterEventAttribute alloc] init];
            attribute.firstCheckId = firstCheckId;
            attribute.registerType = dict[@"registerType"];
            attribute.registerStatus = dict[@"registerStatus"];
            attribute.customProperties = dict[@"customProperties"];
            [[SolarEngineSDK sharedInstance] trackFirstEvent:attribute];
        } else {
            
            SECustomEventAttribute *attribute = [[SECustomEventAttribute alloc] init];
            attribute.eventName = eventName;
            attribute.firstCheckId = firstCheckId;
            attribute.customProperties = dict;
            [[SolarEngineSDK sharedInstance] trackFirstEvent:attribute];
        }
        return 0;
    }
}
int SEPluginLibrary::reportEventImmediately(lua_State* L) {
    @autoreleasepool {
        [[SolarEngineSDK sharedInstance] reportEventImmediately];
        return 0;
    }
}
int SEPluginLibrary::getAttributionData(lua_State *L) {
    
    @autoreleasepool {
        
        
        NSDictionary *attData =  [ [ SolarEngineSDK sharedInstance ] getAttributionData ] ;
        
        if (attData) {
            lua_pushstring(L, [taDictionaryToJson(attData) UTF8String]);
        } else {
            lua_pushstring(L, "");
        }
        return 1;
    }
}






#pragma mark -CALLBACK
int p_initCompletedCallback = LUA_NOREF;
int p_attributionCallback=LUA_NOREF;
int p_deepLinkCallback=LUA_NOREF;
int p_defferedDeepLinkCallback=LUA_NOREF;
int p_trackingAuthorization=LUA_NOREF;



static lua_State *gL_attribution = nullptr;
static lua_State *gL_init = nullptr;
static lua_State *gL_deepLink = nullptr;
static lua_State *gL_defferedDeepLink= nullptr;
static lua_State *gL_trackingAuthorization = nullptr;



int SEPluginLibrary::setAttributionCallback(lua_State *L) {
    gL_attribution = L;
    if (lua_isfunction(L, 1)) {
        lua_pushvalue(L, 1);
        p_attributionCallback = luaL_ref(L, LUA_REGISTRYINDEX);
        [[SolarEngineSDK sharedInstance] setAttributionCallback:^(int code, NSDictionary * _Nullable attributionData) {
            dispatch_async(dispatch_get_main_queue(), ^{
                if (gL_attribution && p_attributionCallback != LUA_NOREF) {
                    lua_rawgeti(gL_attribution, LUA_REGISTRYINDEX, p_attributionCallback);
                    lua_pushinteger(gL_attribution, code);
                    if (attributionData) {
                        lua_pushstring(gL_attribution, [[attributionData description]UTF8String]);
                    } else {
                        lua_pushnil(gL_attribution);
                    }
                    if (lua_pcall(gL_attribution, 2, 0, 0) != 0) {
                        const char *err = lua_tostring(gL_attribution, -1);
                        NSLog(@"[SEPluginLibrary] ❌ Lua callback error: %s", err);
                        lua_pop(gL_attribution, 1);
                    }
                }
            })      ;
        }];
    }
    return 0;
}

int SEPluginLibrary::setInitCompletedCallback(lua_State *L) {
    gL_init = L;
    if (lua_isfunction(L, 1)) {
        lua_pushvalue(L, 1);
        p_initCompletedCallback = luaL_ref(L, LUA_REGISTRYINDEX);
    }
    [[SolarEngineSDK sharedInstance] setInitCompletedCallback:^(int code) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (gL_init && p_initCompletedCallback != LUA_NOREF) {
                lua_rawgeti(gL_init, LUA_REGISTRYINDEX, p_initCompletedCallback);
                lua_pushinteger(gL_init, code);
                
                if (lua_pcall(gL_init, 1, 0, 0) != 0) {
                    const char *err = lua_tostring(gL_init, -1);
                    NSLog(@"[SEPluginLibrary] ❌ Lua callback error: %s", err);
                    lua_pop(gL_init, 1);
                }
            }
        });
    }];
    
    return 0;
}


int SEPluginLibrary::requestTrackingAuthorization(lua_State *L) {
    @autoreleasepool {
        gL_trackingAuthorization = L;

        if (lua_isfunction(L, 1)) {
            // 保存回调引用
            lua_pushvalue(L, 1);
            p_trackingAuthorization = luaL_ref(L, LUA_REGISTRYINDEX);

            // 调用 SDK 的授权接口
            [[SolarEngineSDK sharedInstance] requestTrackingAuthorizationWithCompletionHandler:^(NSUInteger status) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    if (gL_trackingAuthorization && p_trackingAuthorization != LUA_NOREF) {
                        lua_rawgeti(gL_trackingAuthorization, LUA_REGISTRYINDEX, p_trackingAuthorization);
                        lua_pushinteger(gL_trackingAuthorization, (int)status);
                        if (lua_pcall(gL_trackingAuthorization, 1, 0, 0) != 0) {
                            const char *err = lua_tostring(gL_trackingAuthorization, -1);
                            NSLog(@"[SEPluginLibrary] ❌ Lua callback error: %s", err);
                            lua_pop(gL_trackingAuthorization, 1);
                        }
                    }
                });
            }];
        }

        return 0;
    }
}


int SEPluginLibrary::setDeepLinkCallback(lua_State *L) {
    gL_deepLink = L;
    
    if (!lua_isfunction(L, 1)) {
        lua_pushstring(L, "setDeepLinkCallback parameter must be a function");
        lua_error(L);
        return 0;
    }
    
    // 保存 Lua 回调
    lua_pushvalue(L, 1);
    p_deepLinkCallback = luaL_ref(L, LUA_REGISTRYINDEX);
    
    // -------------------------
    // 真 SDK 回调
    // -------------------------
    [[SolarEngineSDK sharedInstance] setDeepLinkCallback:^(int code, SEDeeplinkInfo * _Nullable deeplinkInfo) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (gL_deepLink && p_deepLinkCallback != LUA_NOREF) {
                lua_rawgeti(gL_deepLink, LUA_REGISTRYINDEX, p_deepLinkCallback);
                
                lua_pushinteger(gL_deepLink, code);
                
                if (deeplinkInfo) {
                    lua_newtable(gL_deepLink);
                    
                    if (deeplinkInfo.from) {
                        lua_pushstring(gL_deepLink, [deeplinkInfo.from UTF8String]);
                        lua_setfield(gL_deepLink, -2, "from");
                    }
                    
                    if (deeplinkInfo.sedpLink) {
                        lua_pushstring(gL_deepLink, [deeplinkInfo.sedpLink UTF8String]);
                        lua_setfield(gL_deepLink, -2, "sedpLink");
                    }
                    if(deeplinkInfo.turlId){
                        lua_pushstring(gL_deepLink, [deeplinkInfo.turlId UTF8String]);
                        lua_setfield(gL_deepLink, -2, "turlId");
                    }
                    if(deeplinkInfo.customParams){
                        lua_pushstring(gL_deepLink, [taDictionaryToJson(deeplinkInfo.customParams) UTF8String]);
                        lua_setfield(gL_deepLink, -2, "customParams");
                    }
                } else {
                    lua_pushnil(gL_deepLink);
                }
                
                // 调用 Lua 回调
                if (lua_pcall(gL_deepLink, 2, 0, 0) != 0) {
                    const char *err = lua_tostring(gL_deepLink, -1);
                    NSLog(@"[DeepLink] Lua callback error: %s", err);
                    lua_pop(gL_deepLink, 1);
                }
            }
        });
    }];
    
    // -------------------------
    // MOCK 测试（可选，开发时用）
    // -------------------------
#ifdef SEDEBUG
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        if (gL_deepLink && p_deepLinkCallback != LUA_NOREF) {
            lua_rawgeti(gL_deepLink, LUA_REGISTRYINDEX, p_deepLinkCallback);
            
            lua_pushinteger(gL_deepLink, 0); // code = 0 成功
            
            lua_newtable(gL_deepLink);
            lua_pushstring(gL_deepLink, "mock_from_app");
            lua_setfield(gL_deepLink, -2, "from");
            lua_pushstring(gL_deepLink, "se://mock/deeplink?param=123");
            lua_setfield(gL_deepLink, -2, "sedpLink");
            
            if (lua_pcall(gL_deepLink, 2, 0, 0) != 0) {
                const char *err = lua_tostring(gL_deepLink, -1);
                NSLog(@"[DeepLink MOCK] Lua callback error: %s", err);
                lua_pop(gL_deepLink, 1);
            }
        }
    });
#endif
    
    return 0;
}



int SEPluginLibrary::setDeferredDeepLinkCallback(lua_State *L) {
    gL_defferedDeepLink = L;
    
    if (!lua_isfunction(L, 1)) {
        lua_pushstring(L, "setDeferredDeepLinkCallback parameter must be a function");
        lua_error(L);
        return 0;
    }
    
    // 保存 Lua 回调
    lua_pushvalue(L, 1);
    p_defferedDeepLinkCallback = luaL_ref(L, LUA_REGISTRYINDEX);
    
#ifdef SEDEBUG
    // --------------------------
    // MOCK 数据回调（DEBUG）
    // --------------------------
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        if (gL_defferedDeepLink && p_defferedDeepLinkCallback != LUA_NOREF) {
            lua_rawgeti(gL_defferedDeepLink, LUA_REGISTRYINDEX, p_defferedDeepLinkCallback);
            
            lua_pushinteger(gL_defferedDeepLink, 0); // code = 0
            
            lua_newtable(gL_defferedDeepLink);
            lua_pushstring(gL_defferedDeepLink, "ABC1234");
            lua_setfield(gL_defferedDeepLink, -2, "turlId");
            lua_pushstring(gL_defferedDeepLink, "se://mock/deeplink?param=123");
            lua_setfield(gL_defferedDeepLink, -2, "sedpLink");
            lua_pushstring(gL_defferedDeepLink, "myappscheme://mock");
            lua_setfield(gL_defferedDeepLink, -2, "sedpUrlscheme");
            
            if (lua_pcall(gL_defferedDeepLink, 2, 0, 0) != 0) {
                const char *err = lua_tostring(gL_defferedDeepLink, -1);
                NSLog(@"[DEBUG] DeferredDeepLink callback error: %s", err);
                lua_pop(gL_defferedDeepLink, 1);
            }
        }
    });
#else
    // --------------------------
    // Release: 使用真实 SDK 回调
    // --------------------------
    [[SolarEngineSDK sharedInstance] setDeferredDeepLinkCallbackWithSuccess:^(SEDeferredDeeplinkInfo * _Nullable deeplinkInfo) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (gL_defferedDeepLink && p_defferedDeepLinkCallback != LUA_NOREF) {
                lua_rawgeti(gL_defferedDeepLink, LUA_REGISTRYINDEX, p_defferedDeepLinkCallback);
                
                lua_pushinteger(gL_defferedDeepLink, 0); // code = 0
                
                lua_newtable(gL_defferedDeepLink);
                
                if (deeplinkInfo.turlId) {
                    lua_pushstring(gL_defferedDeepLink, [deeplinkInfo.turlId UTF8String]);
                    lua_setfield(gL_defferedDeepLink, -2, "turlId");
                }
                if (deeplinkInfo.sedpLink) {
                    lua_pushstring(gL_defferedDeepLink, [deeplinkInfo.sedpLink UTF8String]);
                    lua_setfield(gL_defferedDeepLink, -2, "sedpLink");
                }
                if (deeplinkInfo.sedpUrlscheme) {
                    lua_pushstring(gL_defferedDeepLink, [deeplinkInfo.sedpUrlscheme UTF8String]);
                    lua_setfield(gL_defferedDeepLink, -2, "sedpUrlscheme");
                }
                
                if (lua_pcall(gL_defferedDeepLink, 2, 0, 0) != 0) {
                    const char *err = lua_tostring(gL_defferedDeepLink, -1);
                    NSLog(@"DeferredDeepLink success callback error: %s", err);
                    
                    lua_pop(gL_defferedDeepLink, 1);
                }
            }
        });
    } fail:^(NSError * _Nullable error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (gL_defferedDeepLink && p_defferedDeepLinkCallback != LUA_NOREF) {
                lua_rawgeti(gL_defferedDeepLink, LUA_REGISTRYINDEX, p_defferedDeepLinkCallback);
                
                lua_pushinteger(gL_defferedDeepLink, (int)error.code); // code = 错误码
                lua_newtable(gL_defferedDeepLink);
                
                // 附带错误描述
                if (error.localizedDescription) {
                    lua_pushstring(gL_defferedDeepLink, [error.localizedDescription UTF8String]);
                    lua_setfield(gL_defferedDeepLink, -2, "error");
                }
                
                if (lua_pcall(gL_defferedDeepLink, 2, 0, 0) != 0) {
                    const char *err = lua_tostring(gL_defferedDeepLink, -1);
                    NSLog(@"DeferredDeepLink fail callback error: %s", err);
                    lua_pop(gL_defferedDeepLink, 1);
                }
            }
        });
    }];
#endif
    
    return 0;
}


#pragma mark -RC


int SEPluginLibrary::setRemoteDefaultConfig(lua_State *L) {
    @autoreleasepool {
        const char *json = lua_tostring(L, 1);
        
        NSArray *defaultConfig = nil;
        NSString *_config = [NSString stringWithUTF8String:json];
        if (![_config isEqualToString:@"null"]) {
            NSData *data = [_config dataUsingEncoding:NSUTF8StringEncoding];
            NSError *error = nil;
            defaultConfig = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
            SELog(@"[SEPluginLibrary] ✅ setRemoteDefaultConfig: %@", defaultConfig);
            
        }
        
        [[SERemoteConfigManager sharedInstance] setDefaultConfig:defaultConfig];
        return 0;
    }
}
int SEPluginLibrary::setRemoteConfigEventProperties(lua_State *L) {
    @autoreleasepool {
        const char *json = lua_tostring(L, 1);
        NSDictionary *dict = taJsonToDictionary(json);
        [[SERemoteConfigManager sharedInstance] setRemoteConfigEventProperties:dict];
        return 0;
    }
}
int SEPluginLibrary::setRemoteConfigUserProperties(lua_State *L) {
    @autoreleasepool {
        const char *json = lua_tostring(L, 1);
        NSDictionary *dict = taJsonToDictionary(json);
        [[SERemoteConfigManager sharedInstance] setRemoteConfigUserProperties:dict];
        return 0;
    }
}


int SEPluginLibrary::fastFetchRemoteConfig(lua_State *L) {
    @autoreleasepool {
        
        const char *key = lua_tostring(L, 1);
        if (!key) {
            lua_pushstring(L, "");
            return 1;
        }
        
        NSString *keyString = [NSString stringWithUTF8String:key];
        id data = [[SERemoteConfigManager sharedInstance] fastFetchRemoteConfig:keyString];
        
        NSString *msg = convertToNSString(data);
        lua_pushstring(L, [msg UTF8String]);
        return 1;
    }
}


int SEPluginLibrary::fastAllFetchRemoteConfig(lua_State *L) {
    @autoreleasepool {
        NSDictionary *(dic) = [[SERemoteConfigManager sharedInstance] fastFetchRemoteConfig];
        
        if (dic) {
            lua_pushstring(L, [taDictionaryToJson(dic) UTF8String]);
        } else {
            lua_pushstring(L, "");
        }
        return 1;
    }
}

//int p_asyncFetchCallback = LUA_NOREF;
static lua_State *gL_asyncFetch = nullptr;

int p_asyncFetchAllCallback= LUA_NOREF;
static lua_State *gL_asyncFetchAll = nullptr;

int SEPluginLibrary::asyncFetchRemoteConfig(lua_State *L) {
    @autoreleasepool {
        
        gL_asyncFetch = L;
        
        const char *key = lua_tostring(L, 1);
        if (!key) {
            lua_pushstring(L, "asyncFetchRemoteConfig: missing key");
            lua_error(L);
            return 0;
        }
        NSString *keyString = [NSString stringWithUTF8String:key];
        
        // --- 2️⃣ 检查回调函数 ---
        if (!lua_isfunction(L, 2)) {
            lua_pushstring(L, "asyncFetchRemoteConfig: second argument must be a function");
            lua_error(L);
            return 0;
        }
        
        // --- 3️⃣ 保存回调引用 ---
        lua_pushvalue(L, 2);
        int  p_asyncFetchCallback = luaL_ref(L, LUA_REGISTRYINDEX);
        
        // --- 4️⃣ 调用 Objective-C 异步 ---
        [[SERemoteConfigManager sharedInstance]
         asyncFetchRemoteConfig:keyString
         completionHandler:^(id _Nonnull data) {
            
            dispatch_async(dispatch_get_main_queue(), ^{
                lua_State *Lmain = gL_asyncFetch;
                if (!Lmain) return;
                
                if (p_asyncFetchCallback && p_asyncFetchCallback != LUA_NOREF) {
                    // ✅ 先取回函数对象
                    lua_rawgeti(Lmain, LUA_REGISTRYINDEX, p_asyncFetchCallback);
                    
                    if (!lua_isfunction(Lmain, -1)) {
                        NSLog(@"[SEPlugin] asyncFetchRemoteConfig: callback is not function");
                        lua_pop(Lmain, 1);
                        return;
                    }
                    
                    // ✅ 再压参数
                    NSString *msg = convertToNSString(data);
                    lua_pushstring(Lmain, [msg UTF8String]);
                    
                    // ✅ 调用 Lua 函数（参数1个，无返回）
                    if (lua_pcall(Lmain, 1, 0, 0) != 0) {
                        NSLog(@"[SEPlugin] asyncFetchRemoteConfig Lua callback error: %s",
                              lua_tostring(Lmain, -1));
                        lua_pop(Lmain, 1);
                    }
                    
                }
            });
        }];
        
        return 0;
    }
}
//asyncAllFetchRemoteConfig
int SEPluginLibrary::asyncAllFetchRemoteConfig(lua_State *L) {
    @autoreleasepool {
        gL_asyncFetchAll = L;
        
        // 检查参数
        if (!lua_isfunction(L, 1)) {
            lua_pushstring(L, "asyncAllFetchRemoteConfig: first argument must be a function");
            lua_error(L);
            return 0;
        }
        
        // 保存回调函数
        lua_pushvalue(L, 1);
        p_asyncFetchAllCallback = luaL_ref(L, LUA_REGISTRYINDEX);
        
        // 异步调用 RemoteConfig 获取全部配置
        [[SERemoteConfigManager sharedInstance] asyncFetchRemoteConfigWithCompletionHandler:^(NSDictionary * _Nonnull dict) {
            dispatch_async(dispatch_get_main_queue(), ^{
                lua_State *Lmain = gL_asyncFetchAll;
                if (!Lmain) return;
                
                if (p_asyncFetchAllCallback && p_asyncFetchAllCallback != LUA_NOREF) {
                    // 取出 Lua 回调函数
                    lua_rawgeti(Lmain, LUA_REGISTRYINDEX, p_asyncFetchAllCallback);
                    
                    // 将 NSDictionary 转成 JSON 字符串
                    NSString *resultString = @"";
                    if ([dict isKindOfClass:[NSDictionary class]] || [dict isKindOfClass:[NSArray class]]) {
                        NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:nil];
                        if (jsonData) {
                            resultString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
                        }
                    } else if ([dict isKindOfClass:[NSString class]]) {
                        resultString = (NSString *)dict;
                    } else if (dict != nil) {
                        resultString = [dict description];
                    }
                    
                    // 压入参数并执行 Lua 回调
                    lua_pushstring(Lmain, [resultString UTF8String]);
                    if (lua_pcall(Lmain, 1, 0, 0) != 0) {
                        NSLog(@"[SEPlugin] asyncAllFetchRemoteConfig Lua callback error: %s",
                              lua_tostring(Lmain, -1));
                        lua_pop(Lmain, 1);
                    }
                    
                    // 清理引用
                    luaL_unref(Lmain, LUA_REGISTRYINDEX, p_asyncFetchAllCallback);
                    p_asyncFetchAllCallback = LUA_NOREF;
                }
            });
        }];
        
        return 0;
    }
}

#pragma mark -APIEND

#pragma mark -NOT SUPPORT
int SEPluginLibrary::setChannel(lua_State* L) {
    @autoreleasepool {
        
        NSLog (@ "setChannel not support iOS" );
        
        return 0;
    }
}
int SEPluginLibrary::setOaid (lua_State* L) {
    @autoreleasepool {
        NSLog (@ "setOaid not support iOS" );
        return 0;
    }
}
int SEPluginLibrary::setGDPRArea (lua_State* L) {
    @autoreleasepool {
        NSLog (@ "setGDPRArea not support iOS" );
        return 0;
    }
}
int SEPluginLibrary::setGaid (lua_State* L) {
    @autoreleasepool {
        NSLog (@ "setGaid not support iOS" );
        return 0;
    }
}

#pragma mark --END--




static const luaL_Reg kVTable[] = {
    { "preinit", SEPluginLibrary::preinit },
    { "initSdk", SEPluginLibrary::initSdk },
    { "setInitCompletedCallback", SEPluginLibrary::setInitCompletedCallback },
    { "setAttributionCallback", SEPluginLibrary::setAttributionCallback },
    { "setDeferredDeepLinkCallback", SEPluginLibrary::setDeferredDeepLinkCallback },
    
    { "setDeepLinkCallback", SEPluginLibrary::setDeepLinkCallback },
    { "requestTrackingAuthorization", SEPluginLibrary::requestTrackingAuthorization },
    
    
    
    { "setVisitorId", SEPluginLibrary::setVisitorId },
    { "getVisitorId", SEPluginLibrary::getVisitorId },
    
    { "getAccountId", SEPluginLibrary::getAccountId },
    
    { "getDistinctId", SEPluginLibrary::getDistinctId },
    { "login", SEPluginLibrary::login },
    { "logout", SEPluginLibrary::logout },
    
    
    { "setPresetEvent", SEPluginLibrary::setPresetEvent },
    { "setSuperProperties", SEPluginLibrary::setSuperProperties },
    { "unsetSuperProperty", SEPluginLibrary::unsetSuperProperty },
    { "clearSuperProperties", SEPluginLibrary::clearSuperProperties },
    { "getPresetProperties", SEPluginLibrary::getPresetProperties },
    { "userInit", SEPluginLibrary::userInit },
    { "userUpdate", SEPluginLibrary::userUpdate },
    { "userUnset", SEPluginLibrary::userUnset },
    { "userAppend", SEPluginLibrary::userAppend },
    { "userAdd", SEPluginLibrary::userAdd },
    { "userDelete", SEPluginLibrary::userDelete },
    
    { "trackAdImpression", SEPluginLibrary::trackAdImpression },
    { "trackAdClick", SEPluginLibrary::trackAdClick },
    { "trackPurchase", SEPluginLibrary::trackPurchase },
    { "trackRegister", SEPluginLibrary::trackRegister },
    { "trackOrder", SEPluginLibrary::trackOrder },
    { "trackLogin", SEPluginLibrary::trackLogin },
    { "trackAttribution", SEPluginLibrary::trackAttribution },
    
    { "trackOrder", SEPluginLibrary::trackOrder },
    { "trackAppReEngagement", SEPluginLibrary::trackAppReEngagement },
    { "track", SEPluginLibrary::track },
    { "trackFirstEvent", SEPluginLibrary::trackFirstEvent },
    { "eventStart", SEPluginLibrary::eventStart },
    { "eventFinish", SEPluginLibrary::eventFinish },
    
    
    
    { "reportEventImmediately", SEPluginLibrary::reportEventImmediately },
    { "getAttributionData", SEPluginLibrary::getAttributionData },
    
    
    { "setRemoteDefaultConfig", SEPluginLibrary::setRemoteDefaultConfig },
    { "setRemoteConfigEventProperties",  SEPluginLibrary::setRemoteConfigEventProperties },
    { "setRemoteConfigUserProperties",  SEPluginLibrary::setRemoteConfigUserProperties },
    
    { "fastFetchRemoteConfig",  SEPluginLibrary::fastFetchRemoteConfig },
    { "fastAllFetchRemoteConfig", SEPluginLibrary::fastAllFetchRemoteConfig },
    { "asyncFetchRemoteConfig", SEPluginLibrary::asyncFetchRemoteConfig },
    { "asyncAllFetchRemoteConfig", SEPluginLibrary::asyncAllFetchRemoteConfig },
    
    
    
    
    
    
    
    
    
    //not suport
    { "setOaid", SEPluginLibrary::setOaid },
    { "setGDPRArea", SEPluginLibrary::setGDPRArea },
    { "setGaid", SEPluginLibrary::setGaid },
    { "setChannel", SEPluginLibrary::setChannel },
    
    
    
    
    { NULL, NULL }
};

CORONA_EXPORT int luaopen_se_plugin_library(lua_State *L) {
    luaL_register(L, "se.plugin.library", kVTable);
    return 1;
}



