#import "StorytellerSdkGam.h"
#import <React/RCTBridgeModule.h>
#import <React/RCTConvert.h>
#import <React/RCTLog.h>

#ifdef RCT_NEW_ARCH_ENABLED
#import <ReactCommon/RCTTurboModule.h>
using namespace JS::NativeStorytellerSdkGam;
#endif

@interface StorytellerGamSdk : NSObject
- (void)disableGoogleAdsModule;
- (void)setupGAMModule:(NSDictionary *)configuration;
- (void)setupAdMobModule:(NSDictionary *)configuration;
- (void)setAdUnitResult:(NSDictionary *)result;
@property(nonatomic, copy) void (^onAdUnitRequest)(NSDictionary *payload);
@end

@interface StorytellerSdkGam ()
- (void)forwardAdUnitRequestToJS:(NSDictionary *)payload;
@end

@implementation StorytellerSdkGam {
  StorytellerGamSdk *_swiftImplementation;
#ifndef RCT_NEW_ARCH_ENABLED
  BOOL _hasJSListeners;
#endif
}

RCT_EXPORT_MODULE(StorytellerSdkGam)

+ (BOOL)requiresMainQueueSetup
{
  return YES;
}

- (instancetype)init
{
  self = [super init];
  if (self) {
    _swiftImplementation = [StorytellerGamSdk new];
    __weak StorytellerSdkGam *weakSelf = self;
    _swiftImplementation.onAdUnitRequest = ^(NSDictionary *payload) {
      StorytellerSdkGam *strongSelf = weakSelf;
      if (strongSelf == nil) {
        return;
      }
      [strongSelf forwardAdUnitRequestToJS:payload];
    };
  }
  return self;
}

#ifndef RCT_NEW_ARCH_ENABLED
- (NSDictionary *)constantsToExport
{
  return @{ @"GET_AD_UNIT_FOR_REQUEST": @"getAdUnitForRequest" };
}

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

- (void)startObserving
{
  _hasJSListeners = YES;
}

- (void)stopObserving
{
  _hasJSListeners = NO;
}
#endif

#ifdef RCT_NEW_ARCH_ENABLED
- (void)disableGoogleAdsModule
{
  [self disableGoogleAdsModuleWithConfig];
}

- (void)setupGAMModule:(SpecSetupGAMModuleConfiguration &)configuration
{
  NSMutableDictionary *payload = [NSMutableDictionary new];

  auto customTemplate = configuration.customNativeTemplateId();
  if (customTemplate.has_value()) {
    NSMutableDictionary *templateIds = [NSMutableDictionary new];
    NSString *stories = customTemplate->stories();
    NSString *clips = customTemplate->clips();
    if (stories != nil) {
      templateIds[@"stories"] = stories;
    }
    if (clips != nil) {
      templateIds[@"clips"] = clips;
    }
    if (templateIds.count > 0) {
      payload[@"customNativeTemplateId"] = templateIds;
    }
  }

  id<NSObject> customKvps = configuration.customKvps();
  if ([customKvps isKindOfClass:[NSDictionary class]]) {
    payload[@"customKvps"] = (NSDictionary *)customKvps;
  }

  NSString *bottomBannerAdUnit = configuration.bottomBannerAdUnit();
  if (bottomBannerAdUnit != nil) {
    payload[@"bottomBannerAdUnit"] = bottomBannerAdUnit;
  }

  [self setupGAMModuleWithConfig:payload];
}

- (void)setupAdMobModule:(SpecSetupAdMobModuleConfiguration &)configuration
{
  NSMutableDictionary *payload = [NSMutableDictionary new];

  NSString *nativeAdUnit = configuration.nativeAdUnit();
  if (nativeAdUnit != nil) {
    payload[@"nativeAdUnit"] = nativeAdUnit;
  }

  NSString *bannerAdUnit = configuration.bannerAdUnit();
  if (bannerAdUnit != nil) {
    payload[@"bannerAdUnit"] = bannerAdUnit;
  }

  NSString *bottomBannerAdUnit = configuration.bottomBannerAdUnit();
  if (bottomBannerAdUnit != nil) {
    payload[@"bottomBannerAdUnit"] = bottomBannerAdUnit;
  }

  id<NSObject> customKvps = configuration.customKvps();
  if ([customKvps isKindOfClass:[NSDictionary class]]) {
    payload[@"customKvps"] = (NSDictionary *)customKvps;
  }

  if (configuration.enableBannerAdPriority().has_value()) {
    payload[@"enableBannerAdPriority"] = @(configuration.enableBannerAdPriority().value());
  }

  [self setupAdMobModuleWithConfig:payload];
}

- (void)setAdUnitResult:(SpecSetAdUnitResultConfiguration &)configuration
{
  NSMutableDictionary *payload = [NSMutableDictionary new];
  NSString *requestId = configuration.requestId();
  if (requestId == nil) {
    RCTLogError(@"StorytellerSdkGam setAdUnitResult missing requestId");
    return;
  }
  payload[@"requestId"] = requestId;

  NSString *adUnitId = configuration.adUnitId();
  if (adUnitId != nil) {
    payload[@"adUnitId"] = adUnitId;
  }

  [self setAdUnitResultWithConfig:payload];
}

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

#else

RCT_EXPORT_METHOD(disableGoogleAdsModule)
{
  [self disableGoogleAdsModuleWithConfig];
}

RCT_EXPORT_METHOD(setupGAMModule:(NSDictionary *)configuration)
{
  [self setupGAMModuleWithConfig:configuration];
}

RCT_EXPORT_METHOD(setupAdMobModule:(NSDictionary *)configuration)
{
  [self setupAdMobModuleWithConfig:configuration];
}

RCT_EXPORT_METHOD(setAdUnitResult:(NSDictionary *)result)
{
  [self setAdUnitResultWithConfig:result];
}

#endif

- (void)disableGoogleAdsModuleWithConfig
{
  RCTLogInfo(@"[StorytellerSdkGam] disableGoogleAdsModule called");
  [_swiftImplementation disableGoogleAdsModule];
}

- (void)setupGAMModuleWithConfig:(NSDictionary *)configuration
{
  RCTLogInfo(@"[StorytellerSdkGam] setupGAMModuleWithConfig called with payload: %@", configuration);
  [_swiftImplementation setupGAMModule:configuration];
}

- (void)setupAdMobModuleWithConfig:(NSDictionary *)configuration
{
  RCTLogInfo(@"[StorytellerSdkGam] setupAdMobModuleWithConfig called with payload: %@", configuration);
  [_swiftImplementation setupAdMobModule:configuration];
}

- (void)setAdUnitResultWithConfig:(NSDictionary *)result
{
  [_swiftImplementation setAdUnitResult:result];
}

- (void)forwardAdUnitRequestToJS:(NSDictionary *)payload
{
#ifdef RCT_NEW_ARCH_ENABLED
  [self emitGetAdUnitForRequest:payload];
#else
  if (_hasJSListeners) {
    [self sendEventWithName:@"getAdUnitForRequest" body:payload];
  }
#endif
}

@end
