//
//  MoEReactNativeHandler.m
//  ReactNativeMoEngage
//
//  Created by Rakshitha on 04/03/24.
//

#import <Foundation/Foundation.h>
#import "MoEReactEventDispatcher.h"
#import "MoEReactNativeHandler.h"
#import "MoEngageReactUtils.h"
#import "MoEngageReactConstants.h"
#import "MoEngageReactPluginInfo.h"

@import MoEngagePluginBase;

@interface MoEReactNativeHandler() <MoEngagePluginBridgeDelegate>
@end

@implementation MoEReactNativeHandler : NSObject

+(instancetype)sharedInstance{
    static dispatch_once_t onceToken;
    static MoEReactNativeHandler *instance;
    dispatch_once(&onceToken, ^{
        instance = [[MoEReactNativeHandler alloc] init];
    });
    return instance;
}

-(void)setPluginBridgeDelegate:(NSString *)identifier {
    [[MoEngagePluginBridge sharedInstance] setPluginBridgeDelegate:self identifier:identifier];
}

#pragma mark- Initialize methods

-(void)initialize:(NSString *)payload {
    NSDictionary* jsonPayload = [MoEngageReactUtils getJSONRepresentation:payload];
    [[MoEngagePluginBridge sharedInstance] pluginInitialized:jsonPayload];
    if (NSClassFromString(@"MoEngageAppDelegate")) {
        // ignore react native integration info tracking for expo
        return;
    }
    [[[MoEngagePlugin alloc] init] trackPluginInfo:MOE_REACT_PLUGIN_NAME version:MOE_REACT_PLUGIN_VERSION];
}

#pragma mark- Set AppStatus
-(void)setAppStatus:(NSString *)payload {
    NSDictionary* jsonPayload = [MoEngageReactUtils getJSONRepresentation:payload];
    [[MoEngagePluginBridge sharedInstance] setAppStatus:jsonPayload];
}

#pragma mark - trackEvent

-(void)trackEvent:(NSString *)payload {
    NSDictionary* jsonPayload = [MoEngageReactUtils getJSONRepresentation:payload];
    [[MoEngagePluginBridge sharedInstance] trackEvent:jsonPayload];
}

#pragma mark- User Attribute Methods
-(void)setUserAttribute:(NSString *)payload {
    NSDictionary* jsonPayload = [MoEngageReactUtils getJSONRepresentation:payload];
    [[MoEngagePluginBridge sharedInstance] setUserAttribute:jsonPayload];
}

-(void)setAlias:(NSString *)payload {
    NSDictionary* jsonPayload = [MoEngageReactUtils getJSONRepresentation:payload];
    [[MoEngagePluginBridge sharedInstance] setAlias:jsonPayload];
}

#pragma mark- Push Notifications
-(void)registerForPush {
    [[MoEngagePluginBridge sharedInstance] registerForPush];
}

-(void)registerForProvisionalPush {
    if (@available(iOS 12, *)) {
        [[MoEngagePluginBridge sharedInstance] registerForProvisionalPush];
    } else {
        NSLog(@"registerForProvisionalPush is not available below iOS 12.");
    }
}

#pragma mark Show InApp
-(void)showInApp:(NSString *)payload {
    NSDictionary* jsonPayload = [MoEngageReactUtils getJSONRepresentation:payload];
    [[MoEngagePluginBridge sharedInstance] showInApp:jsonPayload];
}

#pragma mark Self handled In App
-(void)getSelfHandledInApp:(NSString *)payload {
    NSDictionary* jsonPayload = [MoEngageReactUtils getJSONRepresentation:payload];
    [[MoEngagePluginBridge sharedInstance] getSelfHandledInApp:jsonPayload];
}

-(void)getSelfHandledInApps:(NSString *)payload resolve:(RCTPromiseResolveBlock) resolve reject:(RCTPromiseRejectBlock)reject {
    NSDictionary* jsonPayload = [MoEngageReactUtils getJSONRepresentation:payload];
    [[MoEngagePluginBridge sharedInstance] getSelfHandledInApps:jsonPayload completionBlock:^(NSDictionary<NSString *,id> * _Nonnull campaignPayload) {
        NSError *err;
        NSData * jsonData = [NSJSONSerialization dataWithJSONObject:campaignPayload options:0 error:&err];
        if (jsonData) {
            NSString *strPayload = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
            resolve(strPayload);
        } else {
            reject(@"Error", @"Error in parsing Self Handled Campaign Payload", [NSError errorWithDomain:@"" code:400 userInfo:@{@"Error reason": @"Error in parsing Self Handled Campaign Payload"}]);
        }
    }];
}

-(void)updateSelfHandledInAppStatus:(NSString *)payload {
    NSDictionary* jsonPayload = [MoEngageReactUtils getJSONRepresentation:payload];
    [[MoEngagePluginBridge sharedInstance] updateSelfHandledImpression:jsonPayload];
}

#pragma mark InApp Contexts

-(void)setAppContext:(NSString *)payload {
    NSDictionary* jsonPayload = [MoEngageReactUtils getJSONRepresentation:payload];
    [[MoEngagePluginBridge sharedInstance] setInAppContext:jsonPayload];
}

-(void)resetAppContext:(NSString *)payload {
    NSDictionary* jsonPayload = [MoEngageReactUtils getJSONRepresentation:payload];
    [[MoEngagePluginBridge sharedInstance] resetInAppContext:jsonPayload];
}

#pragma mark- Reset User
-(void)logout:(NSString *)payload {
    NSDictionary* jsonPayload = [MoEngageReactUtils getJSONRepresentation:payload];
    [[MoEngagePluginBridge sharedInstance] resetUser:jsonPayload];
}

-(void)optOutDataTracking:(NSString *)payload {
    NSDictionary* jsonPayload = [MoEngageReactUtils getJSONRepresentation:payload];
    [[MoEngagePluginBridge sharedInstance] optOutDataTracking:jsonPayload];
}

-(void)showNudge:(NSString *)payload {
    NSDictionary* jsonPayload = [MoEngageReactUtils getJSONRepresentation:payload];
    [[MoEngagePluginBridge sharedInstance] showNudge:jsonPayload];
}

-(void)updateSdkState:(NSString *)payload {
    NSDictionary* jsonPayload = [MoEngageReactUtils getJSONRepresentation:payload];
    [[MoEngagePluginBridge sharedInstance] updateSDKState:jsonPayload];
}

#pragma mark- User Identities
-(void)identifyUser:(NSString *)payload {
    NSDictionary* jsonPayload = [MoEngageReactUtils getJSONRepresentation:payload];
    [[MoEngagePluginBridge sharedInstance] identifyUser:jsonPayload];
}

-(void)getUserIdentities:(NSString *)payload resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
    NSDictionary* jsonPayload = [MoEngageReactUtils getJSONRepresentation:payload];
    [[MoEngagePluginBridge sharedInstance] getUserIdentities:jsonPayload completionHandler:^(NSDictionary<NSString *,NSString *> * _Nonnull identities) {
        NSError *err;
        NSData * jsonData = [NSJSONSerialization dataWithJSONObject:identities options:0 error:&err];
        if (jsonData) {
            NSString *strPayload = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
            dispatch_async(dispatch_get_main_queue(), ^{
                resolve(strPayload);
            });
        } else {
            dispatch_async(dispatch_get_main_queue(), ^{
                reject(@"Error", @"Error in parsing User Identities Payload", err ? : [NSError errorWithDomain:@"" code:400 userInfo:@{@"Error reason": @"Error in parsing User Identities Payload"}]);
            });
        }
    }];
}

#pragma mark- Delegate Method
- (void)sendMessageWithEvent:(NSString *)event message:(NSDictionary<NSString *,id> *)message {
    NSMutableDictionary* updatedDict = [NSMutableDictionary dictionary];
    
    if (message) {
        NSError *err;
        NSData * jsonData = [NSJSONSerialization dataWithJSONObject:message options:0 error:&err];
        if (jsonData) {
            NSString* strPayload = [[NSString alloc] initWithData:jsonData  encoding:NSUTF8StringEncoding];
            updatedDict[kPayload] = strPayload;
        } else {
            NSLog(@"Error converting to dictionary to string %@", err.localizedDescription);
        }
    }
    
    NSDictionary* userInfo = @{kEventName:event,kPayloadDict:updatedDict};
    [self.delegate sendEventWithName:userInfo];
}

@end
