#import "NSureSDK.h"
#import <nSure/nSure.h>

#ifdef RCT_NEW_ARCH_ENABLED
#import <React/RCTBridge+Private.h>
#endif

@implementation NSureSDK

RCT_EXPORT_MODULE(NSureSDK);

+ (BOOL)requiresMainQueueSetup {
  return YES;
}

#ifndef RCT_NEW_ARCH_ENABLED
// ============================================================================
// OLD ARCHITECTURE — callback-based methods
// ============================================================================

- (dispatch_queue_t)methodQueue {
  return dispatch_get_main_queue();
}

RCT_EXPORT_METHOD(initializeWithAppId:(NSString *)appId
                  partnerId:(NSString *)partnerId
                  configBaseUrl:(NSString *)configBaseUrl
                  callback:(RCTResponseSenderBlock)callback)
{
  @try {
    NSure *nsure;
    if (configBaseUrl && configBaseUrl.length > 0 && partnerId && partnerId.length > 0) {
      nsure = [NSure sharedInstanceWithAppID:appId partherID:partnerId configBaseUrl:configBaseUrl];
    } else if (partnerId && partnerId.length > 0) {
      nsure = [NSure sharedInstanceWithAppID:appId partherID:partnerId];
    } else {
      nsure = [NSure sharedInstanceWithAppID:appId];
    }
    callback(@[nsure.deviceId ?: [NSNull null]]);
  } @catch (NSException *exception) {
    callback(@[[NSNull null]]);
  } @catch (...) {
    callback(@[[NSNull null]]);
  }
}

RCT_EXPORT_METHOD(getDeviceIdWithCallback:(RCTResponseSenderBlock)callback)
{
  @try {
    NSure *nsure = [NSure sharedInstance];
    callback(@[nsure.deviceId ?: [NSNull null]]);
  } @catch (NSException *exception) {
    callback(@[[NSNull null]]);
  } @catch (...) {
    callback(@[[NSNull null]]);
  }
}

RCT_EXPORT_METHOD(getVersionWithCallback:(RCTResponseSenderBlock)callback)
{
  @try {
    NSure *nsure = [NSure sharedInstance];
    callback(@[nsure.version ?: [NSNull null]]);
  } @catch (NSException *exception) {
    callback(@[[NSNull null]]);
  } @catch (...) {
    callback(@[[NSNull null]]);
  }
}

#else
// ============================================================================
// NEW ARCHITECTURE — Promise-based methods (TurboModule)
// ============================================================================

- (void)initialize:(NSString *)appId
         partnerId:(NSString *)partnerId
      configBaseUrl:(NSString *)configBaseUrl
           resolve:(RCTPromiseResolveBlock)resolve
            reject:(RCTPromiseRejectBlock)reject
{
  dispatch_async(dispatch_get_main_queue(), ^{
    @try {
      NSure *nsure;
      if (configBaseUrl && configBaseUrl.length > 0 && partnerId && partnerId.length > 0) {
        nsure = [NSure sharedInstanceWithAppID:appId partherID:partnerId configBaseUrl:configBaseUrl];
      } else if (partnerId && partnerId.length > 0) {
        nsure = [NSure sharedInstanceWithAppID:appId partherID:partnerId];
      } else {
        nsure = [NSure sharedInstanceWithAppID:appId];
      }
      resolve(nsure.deviceId ?: [NSNull null]);
    } @catch (NSException *exception) {
      reject(@"NSURE_ERROR", exception.reason ?: exception.name, nil);
    } @catch (...) {
      reject(@"NSURE_ERROR", @"unknown C++ throw", nil);
    }
  });
}

- (void)getDeviceId:(RCTPromiseResolveBlock)resolve
             reject:(RCTPromiseRejectBlock)reject
{
  dispatch_async(dispatch_get_main_queue(), ^{
    @try {
      NSure *nsure = [NSure sharedInstance];
      resolve(nsure.deviceId ?: [NSNull null]);
    } @catch (NSException *exception) {
      reject(@"NSURE_ERROR", exception.reason ?: exception.name, nil);
    } @catch (...) {
      reject(@"NSURE_ERROR", @"unknown C++ throw", nil);
    }
  });
}

- (void)getVersion:(RCTPromiseResolveBlock)resolve
            reject:(RCTPromiseRejectBlock)reject
{
  dispatch_async(dispatch_get_main_queue(), ^{
    @try {
      NSure *nsure = [NSure sharedInstance];
      resolve(nsure.version ?: [NSNull null]);
    } @catch (NSException *exception) {
      reject(@"NSURE_ERROR", exception.reason ?: exception.name, nil);
    } @catch (...) {
      reject(@"NSURE_ERROR", @"unknown C++ throw", nil);
    }
  });
}

- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
    (const facebook::react::ObjCTurboModule::InitParams &)params
{
  try {
    return std::make_shared<facebook::react::NativeNSureSDKSpecJSI>(params);
  } catch (...) {
    return nullptr;
  }
}

#endif

@end
