//
//  CDVIndigitallCustomer.m
//  Indigitall
//
//  Created by indigitall on 8/10/21.
//

#import "CDVIndigitallCustomer.h"
#import <Indigitall/CustomerIndigitall.h>
#import <Indigitall/INChannel.h>
#import <Indigitall/Indigitall.h>

@implementation CDVIndigitallCustomer

- (void)getCustomer:(CDVInvokedUrlCommand *)command {
  [self.commandDelegate runInBackground:^{
    [CustomerIndigitall
        getCustomerWithSuccess:^(INCustomer *_Nonnull customer) {
          [self successWithCustomer:customer command:command];
        }
        failed:^(INError *_Nonnull error) {
          [self failedWithCommand:command];
        }];
  }];
}

- (void)getCustomerInformation:(CDVInvokedUrlCommand *)command {
  NSDictionary *params = command.arguments.firstObject;
  NSArray<NSString *> *fieldNamesList = params[@"fieldNamesList"];
  [self.commandDelegate runInBackground:^{
    [CustomerIndigitall getCustomerInformationWithFieldNames:fieldNamesList
        success:^(NSArray<INCustomerField *> *_Nonnull customerFields) {
          [self successWithCustomerFields:customerFields command:command];
        }
        failed:^(INError *_Nonnull error) {
          [self failedWithCommand:command];
        }];
  }];
}

- (void)assignOrUpdateValueToCustomerFields:(CDVInvokedUrlCommand *)command {
  NSDictionary *params = command.arguments.firstObject;
  [self.commandDelegate runInBackground:^{
    [CustomerIndigitall updateValueToCustomerFieldsWithFields:params
        success:^(INCustomer *_Nonnull customer) {
          [self successWithCustomer:customer command:command];
        }
        failed:^(INError *_Nonnull error) {
          [self failedWithCommand:command];
        }];
  }];
}

- (void)deleteValuesFromCustomerFields:(CDVInvokedUrlCommand *)command {
  NSDictionary *params = command.arguments.firstObject;
  NSArray<NSString *> *fieldNamesList = params[@"fieldNamesList"];
  [self.commandDelegate runInBackground:^{
    [CustomerIndigitall
        deleteValuesFromCustomerFieldsWithFieldNames:fieldNamesList
        success:^(INCustomer *_Nonnull customer) {
          [self successWithCustomer:customer command:command];
        }
        failed:^(INError *_Nonnull error) {
          [self failedWithCommand:command];
        }];
  }];
}

- (void)sendCustomEvent:(CDVInvokedUrlCommand *)command {
  // check arguments are passed
  if (command.arguments.count == 0) {
    NSLog(@"No arguments passed");
    [self failedWithCommand:command];
    return;
  }

  // First we have to read the array and the first object in that array because
  // of how customer is made
  NSArray *paramsArray = [command.arguments firstObject];
  if (![paramsArray isKindOfClass:[NSArray class]] || paramsArray.count == 0) {
    NSLog(@"Invalid argument type: expected NSArray with at least one element");
    [self failedWithCommand:command];
    return;
  }

  // Read dictionary inside array
  NSDictionary *params = [paramsArray firstObject];
  if (![params isKindOfClass:[NSDictionary class]]) {
    NSLog(@"Invalid element type: expected NSDictionary");
    [self failedWithCommand:command];
    return;
  }

  // Attempt to read the eventCode from the dictionary
  NSString *eventCode = params[@"eventCode"];
  if (![eventCode isKindOfClass:[NSString class]]) {
    NSLog(@"Invalid eventCode: expected NSString");
    [self failedWithCommand:command];
    return;
  }

// Attempt to read the eventId from the dictionary
  NSString *eventId = params[@"eventId"];
  if (![eventId isKindOfClass:[NSString class]]) {
    NSLog(@"Invalid eventId: expected NSString");
    [self failedWithCommand:command];
    return;
  }

// Attempt to read the eventAt from the dictionary
  NSString *eventAt = params[@"eventAt"];
  if (![eventAt isKindOfClass:[NSString class]]) {
    NSLog(@"Invalid eventAt: expected NSString");
    [self failedWithCommand:command];
    return;
  }

  // Attempt to read the customData from the dictionary
  NSDictionary *customData = params[@"customData"];
  if (![customData isKindOfClass:[NSDictionary class]]) {
    NSLog(@"Invalid customData: expected NSDictionary");
    [self failedWithCommand:command];
    return;
  }
  // Native SDK method call
  [self.commandDelegate runInBackground:^{
    [CustomerIndigitall sendCustomerCustomEvent:customData
        eventCode:eventCode
        eventId:eventId
        eventAt:eventAt
        success:^(INCustomer *_Nonnull customer) {
          [self successWithCustomer:customer command:command];
        }
        failed:^(INError *_Nonnull error) {
          [self failedWithCommand:command];
        }];
  }];
}

- (void)link:(CDVInvokedUrlCommand *)command {
  NSDictionary *params = command.arguments.firstObject;
  NSString *code = params[@"externalCode"];
  [self.commandDelegate runInBackground:^{
    if (code != nil) {
      INDevice *device = [[[INDevice alloc] init] saveExternalCode:code];
      [INDefaults setExternalId:device.externalCode];
      [CustomerIndigitall
          linkCustomerWithChannel:[self getChannel:params[@"channel"]]
          success:^{
            [self successWithCommand:command];
          }
          failed:^(INError *_Nonnull error) {
            [self failedWithCommand:command];
          }];
    }
  }];
}

- (void)unlink:(CDVInvokedUrlCommand *)command {
  NSDictionary *params = command.arguments.firstObject;
  [self.commandDelegate runInBackground:^{
    [Indigitall
        logOutWithSuccess:^(INDevice *_Nonnull device) {
          [CustomerIndigitall
              unlinkCustomerWithChannel:[self getChannel:params[@"channel"]]
              success:^{
                [self successWithCommand:command];
              }
              failed:^(INError *_Nonnull error) {
                [self failedWithCommand:command];
              }];
        }
        onError:^(INError *_Nonnull error) {
          [self failedWithCommand:command];
        }];
  }];
}

- (int)getChannel:(NSString *)channel {
  int channelType = 0;
  if ([channel isEqualToString:@"inapp"])
    channelType = 1;
  if ([channel isEqualToString:@"chat"])
    channelType = 2;
  return channelType;
}

- (NSDictionary *)jsonFromCustomer:(INCustomer *)customer {
  NSMutableDictionary *obj = [[NSMutableDictionary alloc] init];
  if (customer != nil) {
    obj = [@{
      @"id" : customer._id ?: @"",
      @"customerId" : customer._id ?: @"",
      @"applicationId" : customer.applicationId ?: @"",
      @"createdAt" : customer.createdAt ?: @"",
      @"updatedAt" : customer.updatedAt ?: @""
    } mutableCopy];
  }
  return [obj copy];
}

- (NSArray<NSDictionary *> *)jsonFromCustomerFields:
    (NSArray<INCustomerField *> *)customerFields {
  NSMutableArray<NSDictionary *> *array = [[NSMutableArray alloc] init];
  for (int i = 0; i < customerFields.count; i++) {
    if (customerFields[i].customerFieldKey &&
        customerFields[i].customerFieldValue) {
      NSMutableDictionary *obj = [[NSMutableDictionary alloc] init];
      obj = [@{
        customerFields[i]
            .customerFieldKey : customerFields[i]
            .customerFieldValue,
      } mutableCopy];
      [array addObject:[obj copy]];
    }
  }
  return [array copy];
}

- (void)successWithCustomer:(INCustomer *)customer
                    command:(CDVInvokedUrlCommand *)command {
  NSDictionary *data = [self jsonFromCustomer:customer];
  CDVPluginResult *result =
      [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
                    messageAsDictionary:data];
  [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
}

- (void)successWithCustomerFields:(NSArray<INCustomerField *> *)customerfields
                          command:(CDVInvokedUrlCommand *)command {
  NSArray<NSDictionary *> *data = [self jsonFromCustomerFields:customerfields];
  CDVPluginResult *result =
      [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
                         messageAsArray:data];
  [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
}

- (void)successWithCommand:(CDVInvokedUrlCommand *)command {
  CDVPluginResult *result =
      [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
  [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
}

- (void)failedWithCommand:(CDVInvokedUrlCommand *)command {
  CDVPluginResult *result =
      [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
  [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
}

@end
