#if RCT_NEW_ARCH_ENABLED

#import "CheckoutModule.h"

#if __has_include(<CheckoutReactNativeComponents/CheckoutReactNativeComponents-Swift.h>)
  #import <CheckoutReactNativeComponents/CheckoutReactNativeComponents-Swift.h>
#else
  #import <CheckoutReactNativeComponents-Swift.h>
#endif

@interface CheckoutModule()
@end

@implementation CheckoutModule

- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const facebook::react::ObjCTurboModule::InitParams &)params {
  return std::make_shared<facebook::react::NativeCheckoutModuleSpecJSI>(params);
}

- (void)initialize:(JS::NativeCheckoutModule::InitializeArgs &)args
           resolve:(nonnull RCTPromiseResolveBlock)resolve
            reject:(nonnull RCTPromiseRejectBlock)reject {
  NSMutableDictionary *argsDict = [[NSMutableDictionary alloc] init];
  
  argsDict[@"environment"] = args.environment();
  argsDict[@"publicKey"] = args.publicKey();
  argsDict[@"paymentSession"] = args.paymentSession();
  argsDict[@"locale"] = args.locale();
  argsDict[@"translations"] = args.translations();
  argsDict[@"style"] = args.style();
  argsDict[@"merchantIdentifier"] = args.merchantIdentifier();

  facebook::react::LazyVector<NSString *> callbacksVec = args.registeredCallbacks();
  NSMutableArray<NSString *> *callbacksArray = [NSMutableArray arrayWithCapacity:callbacksVec.size()];
  for (std::int32_t i = 0, n = callbacksVec.size(); i < n; ++i) {
    NSString *value = callbacksVec[i];
    if (value != nil) {
      [callbacksArray addObject:value];
    }
  }
  argsDict[@"registeredCallbacks"] = callbacksArray;
  
  CheckoutModuleHandler *handler = [CheckoutModuleHandler sharedInstance];
  [handler initializeWithArgs:argsDict completion:^(NSError * _Nullable error) {
      if (error) {
          NSString *code = [NSString stringWithFormat:@"%ld", (long)error.code];
          reject(code, error.localizedDescription, error);
      } else {
          resolve(@(YES));
      }
  }];
}

- (void)clear:(nonnull RCTPromiseResolveBlock)resolve reject:(nonnull RCTPromiseRejectBlock)reject {
  CheckoutModuleHandler *handler = [CheckoutModuleHandler sharedInstance];
  BOOL success = [handler clear];
  if (success) {
      resolve(@(YES));
  } else {
      NSError *error = [CheckoutErrorBridge errorFor:CheckoutErrorClearFailed];
      NSString *code = [NSString stringWithFormat:@"%ld", (long)error.code];
      reject(code, error.localizedDescription, error);
  }
}

- (void)resolveSubmit:(nonnull NSString *)callbackId
                 args:(JS::NativeCheckoutModule::APICallResult &)args
              resolve:(nonnull RCTPromiseResolveBlock)resolve
               reject:(nonnull RCTPromiseRejectBlock)reject {
  NSMutableDictionary *argsDict = [[NSMutableDictionary alloc] init];
  argsDict[@"success"] = @(args.success());
  
  if (args.paymentSessionSubmissionResult()) {
    auto psr = args.paymentSessionSubmissionResult();
    NSMutableDictionary *psrDict = [[NSMutableDictionary alloc] init];
    psrDict[@"id"] = psr->id_();
    psrDict[@"type"] = psr->type();
    psrDict[@"status"] = psr->status();
    if (psr->action()) {
      auto action = psr->action();
      NSMutableDictionary *actionDict = [[NSMutableDictionary alloc] init];
      actionDict[@"type"] = action->type();
      if (action->url()) {
        actionDict[@"url"] = action->url();
      }
      psrDict[@"action"] = actionDict;
    }
    if (psr->declineReason()) {
      psrDict[@"declineReason"] = psr->declineReason();
    }
    argsDict[@"paymentSessionSubmissionResult"] = psrDict;
  }
  
  CheckoutModuleHandler *handler = [CheckoutModuleHandler sharedInstance];
  [handler resolveSubmitWithCallbackId:callbackId
                                  args:argsDict
                             completion:^(NSError * _Nullable error) {
    if (error) {
      NSString *code = [NSString stringWithFormat:@"%ld", (long)error.code];
      reject(code, error.localizedDescription, error);
    } else {
      resolve(@(YES));
    }
  }];
}


- (void)resolveTokenized:(nonnull NSString *)callbackId
                 success:(BOOL)success
                   error:(NSString * _Nullable)error
                 resolve:(nonnull RCTPromiseResolveBlock)resolve
                  reject:(nonnull RCTPromiseRejectBlock)reject { 
  CheckoutModuleHandler *handler = [CheckoutModuleHandler sharedInstance];
  [handler resolveTokenizedWithCallbackId:callbackId
                                  success:success
                                    error:error
                               completion:^(NSError * _Nullable handlerError) {
    if (handlerError) {
      NSString *code = [NSString stringWithFormat:@"%ld", (long)handlerError.code];
      reject(code, handlerError.localizedDescription, handlerError);
    } else {
      resolve(@(YES));
    }
  }];
}


+ (NSString *)moduleName {
  return @"CheckoutModule";
}

@end
#endif
