/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#import <Foundation/Foundation.h>
#import <XCTest/XCTest.h>

#import <RCTTest/RCTTestRunner.h>

#import <React/RCTBridge.h>
#import <React/RCTBridgeModule.h>
#import <React/RCTInitializing.h>
#import <React/RCTJavaScriptExecutor.h>
#import <React/RCTUIManager.h>
#import <React/RCTViewManager.h>

@interface RCTTestViewManager : RCTViewManager
@end

@implementation RCTTestViewManager

RCT_EXPORT_MODULE()

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-implementations"

- (NSArray<NSString *> *)customBubblingEventTypes
{
  return @[ @"foo" ];
}

#pragma clang diagnostic pop

@end

@interface RCTNotificationObserverModule : NSObject <RCTBridgeModule, RCTInitializing>

@property (nonatomic, assign) BOOL didDetectViewManagerInit;

@end

@implementation RCTNotificationObserverModule

@synthesize bridge = _bridge;

RCT_EXPORT_MODULE()

- (void)initialize
{
  [[NSNotificationCenter defaultCenter] addObserver:self
                                           selector:@selector(didInitViewManager:)
                                               name:RCTDidInitializeModuleNotification
                                             object:nil];
}

- (void)didInitViewManager:(NSNotification *)note
{
  id<RCTBridgeModule> module = note.userInfo[@"module"];
  if ([module isKindOfClass:[RCTTestViewManager class]]) {
    _didDetectViewManagerInit = YES;
  }
}

@end

@interface RCTModuleInitNotificationRaceTests : XCTestCase <RCTBridgeDelegate> {
  RCTBridge *_bridge;
  RCTNotificationObserverModule *_notificationObserver;
}
@end

@implementation RCTModuleInitNotificationRaceTests

- (NSURL *)sourceURLForBridge:(__unused RCTBridge *)bridge
{
  NSBundle *bundle = [NSBundle bundleForClass:[self class]];
  return [bundle URLForResource:@"RNTesterUnitTestsBundle" withExtension:@"js"];
}

- (NSArray *)extraModulesForBridge:(__unused RCTBridge *)bridge
{
  return @[ [RCTTestViewManager new], _notificationObserver ];
}

- (void)setUp
{
  [super setUp];

  _notificationObserver = [RCTNotificationObserverModule new];
  _bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:nil];

  dispatch_async(dispatch_get_main_queue(), ^{
    [[self->_bridge uiManager] constantsToExport];
  });
}

- (void)tearDown
{
  [super tearDown];

  _notificationObserver = nil;
  [_bridge invalidate];
  _bridge = nil;
}

- (void)testViewManagerNotInitializedBeforeSetBridgeModule
{
  RCT_RUN_RUNLOOP_WHILE(!_notificationObserver.didDetectViewManagerInit);
}

@end
