// DEV-only fault-injection module. Compiled only when DEBUG=1.
// Plain RCTBridgeModule (not TurboModule) so codegen doesn't ship Spec
// strings via the ReactCodegen Pod; New Arch reaches it via legacy interop.

#import "NSureSDKCrashLab.h"

#if DEBUG

#include <stdexcept>

static inline void NSureCrashLabThrowCpp() {
  throw std::runtime_error("intentional jsi cpp throw");
}

@implementation NSureSDKCrashLab

RCT_EXPORT_MODULE(NSureSDKCrashLab);

+ (BOOL)requiresMainQueueSetup {
  return YES;
}

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

// Callback contract: callback(@[NSNull]) → success; callback(@[errorString])
// → caught crash, JS rejects with that string as NSURE_ERROR message.
RCT_EXPORT_METHOD(crashWithKind:(NSString *)kind
                       callback:(RCTResponseSenderBlock)callback)
{
  @try {
    if ([kind isEqualToString:@"objcException"]) {
      @throw [NSException exceptionWithName:@"NSureCrashLab"
                                     reason:@"intentional objc exception"
                                   userInfo:nil];
    } else if ([kind isEqualToString:@"iosNSExceptionUncaught"]) {
      dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
        @throw [NSException exceptionWithName:@"NSureCrashLab"
                                       reason:@"intentional uncaught nsexception"
                                     userInfo:nil];
      });
      callback(@[[NSNull null]]);
      return;
    } else if ([kind isEqualToString:@"iosBadAccess"]) {
      // __builtin_trap aborts regardless of optimization level (UB writes
      // to NULL can be elided).
      __builtin_trap();
    } else if ([kind isEqualToString:@"iosJsiCppThrow"]) {
      NSureCrashLabThrowCpp();
      callback(@[[NSNull null]]);
      return;
    } else {
      callback(@[[NSString stringWithFormat:@"unknown crash kind: %@", kind]]);
      return;
    }
  } @catch (NSException *exception) {
    callback(@[exception.reason ?: exception.name ?: @"objc exception"]);
  } @catch (...) {
    callback(@[@"unknown C++ throw"]);
  }
}

@end

#endif // DEBUG
