#import "TBLRNTTurboModule.h"
#import "TBLRNTClassicPage.h"
#import "TBLRNTClassicPageDelegate.h"
#import "TBLRNTClassicPagesMap.h"
#import "TBLRNTClassicUnit.h"
#import "TBLRNTConstants.h"
#import "TBLRNTUtils.h"
#import <TaboolaSDK/TaboolaSDK.h>

@implementation TBLRNTTurboModule
RCT_EXPORT_MODULE()

#pragma mark - Taboola

- (void)init:(NSString *)publisherName {
  TBLPublisherInfo *publisherinfo =
      [[TBLPublisherInfo alloc] initWithPublisherName:publisherName];
  [Taboola initWithPublisherInfo:publisherinfo];
}

- (void)setGlobalExtraProperties:(nonnull NSDictionary *)extraProperties {
  [Taboola setGlobalExtraProperties:extraProperties];
}

- (void)setLogLevel:(double)level {
  switch ((int)level) {
  case LogLevelVerbose:
    [Taboola setLogLevel:LogLevelVerbose];
    break;
  case LogLevelDebug:
    [Taboola setLogLevel:LogLevelDebug];
    break;
  case LogLevelInfo:
    [Taboola setLogLevel:LogLevelInfo];
    break;
  case LogLevelWarning:
    [Taboola setLogLevel:LogLevelWarning];
    break;
  case LogLevelError:
    [Taboola setLogLevel:LogLevelError];
    break;
  default:
    return;
  }
}

#pragma mark - TBLRNTClassicPage

- (void)build:(nonnull NSString *)pageId
        placement:(nonnull NSString *)placement
             mode:(nonnull NSString *)mode
    placementType:(double)placementType
          resolve:(nonnull RCTPromiseResolveBlock)resolve
           reject:(nonnull RCTPromiseRejectBlock)reject {
  TBLRNTClassicPage *classicPage = [TBLRNTUtils getClassicPageForPageId:pageId];

  dispatch_sync(dispatch_get_main_queue(), ^{
    NSString *unitID = [classicPage build:placement mode:mode];
    resolve(unitID);
  });
}

- (nonnull NSString *)getClassicPage:(nonnull NSString *)pageUrl
                            pageType:(nonnull NSString *)pageType {
  // Create the delegate
  TBLRNTClassicPageDelegate *rctClassicPageDelegate =
      [[TBLRNTClassicPageDelegate alloc] init];

  // Set the callbacks
  rctClassicPageDelegate.onResizeCallback = ^(NSDictionary *_Nonnull params) {
    [self emitOnResize:params];
  };

  rctClassicPageDelegate.onItemClickCallback =
      ^(NSDictionary *_Nonnull params) {
        [self emitOnItemClick:params];
      };

  rctClassicPageDelegate.onTaboolaWidgetOnTopCallback =
      ^(NSDictionary *_Nonnull params) {
        [self emitOnTaboolaWidgetOnTop:params];
      };

  rctClassicPageDelegate.onAdReceiveSuccessCallback =
      ^(NSDictionary *_Nonnull params) {
        [self emitOnAdReceiveSuccess:params];
      };

  rctClassicPageDelegate.onAdReceiveFailCallback =
      ^(NSDictionary *_Nonnull params) {
        [self emitOnAdReceiveFail:params];
      };

  rctClassicPageDelegate.onUpdateContentCompletedCallback =
      ^(NSDictionary *_Nonnull params) {
        [self emitOnUpdateContentCompleted:params];
      };

  rctClassicPageDelegate.onEventCallback = ^(NSDictionary *_Nonnull params) {
    [self emitOnEvent:params];
  };

  TBLRNTClassicPage *tblClassicPage =
      [[TBLRNTClassicPage alloc] initWithPageType:pageType
                                          pageUrl:pageUrl
                                         delegate:rctClassicPageDelegate];

  NSString *tblClassicPageId = [tblClassicPage tblRNTClassicPageId];

  NSMutableDictionary *tblClassicPagesMap =
      [[TBLRNTClassicPagesMap sharedObject] tblClassicPagesMap];
  [tblClassicPagesMap setObject:@{
    kTBLClassicPageKey : tblClassicPage,
    kTBLRntClassicPageDelegateKey : rctClassicPageDelegate
  }
                         forKey:tblClassicPageId];

  return tblClassicPageId;
}

- (void)removePage:(nonnull NSString *)pageId {
  TBLRNTClassicPage *classicPage = [self getClassicPage:pageId];
  if (classicPage) {
    NSMutableDictionary *tblClassicPagesMap =
        [[TBLRNTClassicPagesMap sharedObject] tblClassicPagesMap];
    [tblClassicPagesMap removeObjectForKey:pageId];
  }
}

- (void)setPageExtraProperties:(nonnull NSString *)pageId
               extraProperties:(nonnull NSDictionary *)extraProperties {
  TBLRNTClassicPage *classicPage = [self getClassicPage:pageId];
  if (!classicPage) {
    return;
  }
  [classicPage setPageExtraProperties:extraProperties];
}

- (void)clearAllFetchRequests:(nonnull NSString *)pageId {
  TBLRNTClassicPage *classicPage = [self getClassicPage:pageId];
  if (!classicPage) {
    return;
  }
  [classicPage clearAllFetchRequests];
}

- (void)fetchAllUnitsContent:(nonnull NSString *)pageId {
  TBLRNTClassicPage *classicPage = [self getClassicPage:pageId];
  if (!classicPage) {
    return;
  }
  [classicPage fetchAllUnitsContentOnly];
}

- (void)refreshPage:(nonnull NSString *)pageId {
  TBLRNTClassicPage *classicPage = [self getClassicPage:pageId];
  if (!classicPage) {
    return;
  }
  [classicPage fetchAllUnitsContent];
}

- (void)resetPage:(nonnull NSString *)pageId {
  TBLRNTClassicPage *classicPage = [self getClassicPage:pageId];
  if (!classicPage) {
    return;
  }
  dispatch_sync(dispatch_get_main_queue(), ^{
    [classicPage reset];
  });
}

- (void)setFetchingPolicy:(NSString *)pageId
           fetchingPolicy:(double)fetchingPolicy {
  TBLRNTClassicPage *classicPage = [self getClassicPage:pageId];
  if (!classicPage) {
    return;
  }

  TBLFetchingPolicy policy;
  switch ((int)fetchingPolicy) {
  case FetchingPolicySerial:
    policy = FetchingPolicySerial;
    break;
  case FetchingPolicyParallel:
    policy = FetchingPolicyParallel;
    break;
  default:
    policy = FetchingPolicySerial;
    break;
  }

  [classicPage setFetchingPolicy:policy];
}

- (void)setPageId:(nonnull NSString *)currentPageId
    updatedPageId:(nonnull NSString *)updatedPageId {
  TBLRNTClassicPage *classicPage = [self getClassicPage:currentPageId];
  if (!classicPage) {
    return;
  }
  [classicPage setPageId:updatedPageId];
}

- (void)setSerialFetchTimeout:(nonnull NSString *)pageId
                timeoutMillis:(double)timeoutMillis {
  TBLRNTClassicPage *classicPage = [self getClassicPage:pageId];
  if (!classicPage) {
    return;
  }
  [classicPage setSerialDelay:timeoutMillis];
}

- (void)setTargetType:(nonnull NSString *)pageId
           targetType:(nonnull NSString *)targetType {
  TBLRNTClassicPage *classicPage = [self getClassicPage:pageId];
  if (!classicPage) {
    return;
  }
  [classicPage setTargetType:targetType];
}

- (void)setUserId:(nonnull NSString *)pageId userId:(nonnull NSString *)userId {
  TBLRNTClassicPage *classicPage = [self getClassicPage:pageId];
  if (!classicPage) {
    return;
  }
  [classicPage setUserId:userId];
}

- (void)restPage:(nonnull NSString *)pageId {
  TBLRNTClassicPage *classicPage = [self getClassicPage:pageId];
  if (!classicPage) {
    return;
  }

  dispatch_sync(dispatch_get_main_queue(), ^{
    [classicPage reset];
  });
}

- (void)setPageTargetType:(nonnull NSString *)pageId
               targetType:(nonnull NSString *)targetType {
  TBLRNTClassicPage *classicPage = [self getClassicPage:pageId];
  if (!classicPage) {
    return;
  }
  [classicPage setTargetType:targetType];
}

- (void)setPageUserId:(nonnull NSString *)pageId
               userId:(nonnull NSString *)userId {
  TBLRNTClassicPage *classicPage = [self getClassicPage:pageId];
  if (!classicPage) {
    return;
  }
  [classicPage setUserId:userId];
}

- (void)setPagePublisher:(nonnull NSString *)pageId
               publisher:(nonnull NSString *)publisher {
  // Not supported on iOS
  NSLog(@"%@", kNotSupportedOnIOSErrorMsg);
}

- (void)setPageTag:(nonnull NSString *)pageId tag:(nonnull NSString *)tag {
  // Not supported on iOS
  NSLog(@"%@", kNotSupportedOnIOSErrorMsg);
}

- (void)setPageType:(nonnull NSString *)pageId
           pageType:(nonnull NSString *)pageType {
  // Not supported on iOS
  NSLog(@"%@", kNotSupportedOnIOSErrorMsg);
}

- (void)setPageUrl:(nonnull NSString *)pageId
           pageUrl:(nonnull NSString *)pageUrl {
  // Not supported on iOS
  NSLog(@"%@", kNotSupportedOnIOSErrorMsg);
}

- (void)setPublisher:(nonnull NSString *)pageId
           publisher:(nonnull NSString *)publisher {
  // Not supported on iOS
  NSLog(@"%@", kNotSupportedOnIOSErrorMsg);
}

- (void)setTag:(nonnull NSString *)pageId tag:(nonnull NSString *)tag {
  // Not supported on iOS
  NSLog(@"%@", kNotSupportedOnIOSErrorMsg);
}

- (NSString *_Nullable)getPageViewId:(nonnull NSString *)pageId {
  return kNotSupportedOnIOSErrorMsg;
}

- (void)setAutoResizeHeight:(nonnull NSString *)pageId
           autoResizeHeight:(BOOL)autoResizeHeight {
  // Not supported on iOS
  NSLog(@"%@", kNotSupportedOnIOSErrorMsg);
}

#pragma mark - TBLClassicUnit

- (void)clearUnit:(nonnull NSString *)pageId unitId:(nonnull NSString *)unitId {
  // Not supported on iOS
  NSLog(@"%@", kNotSupportedOnIOSErrorMsg);
}

- (void)fetchContent:(nonnull NSString *)pageId
              unitId:(nonnull NSString *)unitId {
  TBLRNTClassicUnit *tblClassicUnit = [self getClassicUnit:pageId unitId:unitId];
  if (!tblClassicUnit) {
    return;
  }
  
  [tblClassicUnit fetchContentOnly];
}

- (void)refreshUnit:(nonnull NSString *)pageId
             unitId:(nonnull NSString *)unitId {
  TBLRNTClassicUnit *tblClassicUnit = [self getClassicUnit:pageId unitId:unitId];
  if (!tblClassicUnit) {
    return;
  }
  
  [tblClassicUnit fetchContent];
}

- (void)updateContent:(nonnull NSString *)pageId
               unitId:(nonnull NSString *)unitId {
  // Not implemented
  NSLog(@"%@", kNotSupportedOnIOSErrorMsg);
}

- (void)resetUnit:(nonnull NSString *)pageId unitId:(nonnull NSString *)unitId {
  TBLRNTClassicUnit *tblClassicUnit = [self getClassicUnit:pageId unitId:unitId];
  if (!tblClassicUnit) {
    return;
  }
  
  [tblClassicUnit reset];
}

- (void)setUnitExtraProperties:(nonnull NSString *)pageId
                        unitId:(nonnull NSString *)unitId
               extraProperties:(nonnull NSDictionary *)extraProperties {
  TBLRNTClassicUnit *tblClassicUnit = [self getClassicUnit:pageId unitId:unitId];
  if (!tblClassicUnit) {
    return;
  }

  [tblClassicUnit setExtraProperties:extraProperties];
}

- (void)setShouldHandleOrganicClicks:(nonnull NSString *)pageId
                              unitId:(nonnull NSString *)unitId
           shouldHandleOrganicClicks:(BOOL)shouldHandleOrganicClicks {
  TBLRNTClassicUnit *tblClassicUnit = [self getClassicUnit:pageId unitId:unitId];
  if (!tblClassicUnit) {
    return;
  }

  [tblClassicUnit setShouldTaboolaHandleOrganicClicks:shouldHandleOrganicClicks];
}

- (void)setPublisherName:(nonnull NSString *)pageId
                  unitId:(nonnull NSString *)unitId
           publisherName:(nonnull NSString *)publisherName {
  // Not supported on iOS
  NSLog(@"%@", kNotSupportedOnIOSErrorMsg);
}

- (void)setTag:(nonnull NSString *)pageId
        unitId:(nonnull NSString *)unitId
           tag:(nonnull NSString *)tag {
  // Not implemented
  NSLog(@"%@", kNotSupportedOnIOSErrorMsg);
}

- (void)setUnitTargetType:(nonnull NSString *)pageId
                   unitId:(nonnull NSString *)unitId
               targetType:(nonnull NSString *)targetType {
  // Not implemented
  NSLog(@"%@", kNotSupportedOnIOSErrorMsg);
}

- (void)setUnitUserId:(nonnull NSString *)pageId
               unitId:(nonnull NSString *)unitId
               userId:(nonnull NSString *)userId {
  // Not implemented
  NSLog(@"%@", kNotSupportedOnIOSErrorMsg);
}

- (void)setPageIdFromUnit:(nonnull NSString *)pageId
                   unitId:(nonnull NSString *)unitId
                newPageId:(nonnull NSString *)newPageId {
  // Not supported on iOS
  NSLog(@"%@", kNotSupportedOnIOSErrorMsg);
}

#pragma mark - TemplateJS

- (void)disableTRCCache:(nonnull NSString *)pageId
                 unitId:(nonnull NSString *)unitId {
  TBLRNTClassicUnit *tblClassicUnit = [self getClassicUnit:pageId unitId:unitId];
  if (!tblClassicUnit) {
    return;
  }

  [[tblClassicUnit templateJs] setDisableTrcCache:YES];
}

- (void)requestCampaigns:(nonnull NSString *)pageId
                  unitId:(nonnull NSString *)unitId
               campaigns:(NSArray<NSNumber *> *)campaigns {
  TBLRNTClassicUnit *tblClassicUnit = [self getClassicUnit:pageId unitId:unitId];
  if (!tblClassicUnit) {
    return;
  }

  [[tblClassicUnit templateJs] setCampaings:campaigns];
}

- (void)requestGeo:(nonnull NSString *)pageId
            unitId:(nonnull NSString *)unitId
               geo:(nonnull NSString *)geo {
  TBLRNTClassicUnit *tblClassicUnit = [self getClassicUnit:pageId unitId:unitId];
  if (!tblClassicUnit) {
    return;
  }

  [[tblClassicUnit templateJs] setRequestGeo:geo];
}

- (void)setSpecificTRCServer:(nonnull NSString *)pageId
                      unitId:(nonnull NSString *)unitId
               trcServerName:(nonnull NSString *)trcServerName {
  TBLRNTClassicUnit *tblClassicUnit = [self getClassicUnit:pageId unitId:unitId];
  if (!tblClassicUnit) {
    return;
  }

  [[tblClassicUnit templateJs] setSpecificTRCServer:trcServerName];
}

- (void)setVideoCampaignFormat:(nonnull NSString *)pageId
                        unitId:(nonnull NSString *)unitId
                 videoCampaign:(nonnull NSString *)videoCampaign {
  TBLRNTClassicUnit *tblClassicUnit = [self getClassicUnit:pageId unitId:unitId];
  if (!tblClassicUnit) {
    return;
  }

  [[tblClassicUnit templateJs] setVideoCampaignFormat:videoCampaign];
}

- (void)setTrcDebugMode:(nonnull NSString *)pageId
                      unitId:(nonnull NSString *)unitId
    shouldEnableTrcDebugMode:(BOOL)shouldEnableTrcDebugMode {
  // Not supported on iOS
  NSLog(@"%@", kNotSupportedOnIOSErrorMsg);
}

- (void)addCustomQueryParams:(nonnull NSString *)pageId
                      unitId:(nonnull NSString *)unitId
                    queryKey:(nonnull NSString *)queryKey
                  queryValue:(nonnull NSString *)queryValue {
  TBLRNTClassicUnit *tblClassicUnit = [self getClassicUnit:pageId unitId:unitId];
  if (!tblClassicUnit) {
    return;
  }

  [[tblClassicUnit templateJs] setQueryItemAtKey:queryKey value:queryValue];
}

- (void)setUnitPageType:(nonnull NSString *)pageId unitId:(nonnull NSString *)unitId pageType:(nonnull NSString *)pageType { 
  // Not supported on iOS
  NSLog(@"%@", kNotSupportedOnIOSErrorMsg);
}


- (void)setUnitPageUrl:(nonnull NSString *)pageId unitId:(nonnull NSString *)unitId pageUrl:(nonnull NSString *)pageUrl { 
  // Not supported on iOS
  NSLog(@"%@", kNotSupportedOnIOSErrorMsg);
}


#pragma mark - TurboModule

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

// Helper method for getting classic page
- (nullable TBLRNTClassicPage *)getClassicPage:(NSString *)pageId {
    TBLRNTClassicPage *classicPage = [TBLRNTUtils getClassicPageForPageId:pageId];
    if (!classicPage) {
        NSLog(@"Error: Classic page not found - pageId: %@", pageId);
    }
    return classicPage;
}

// Helper method for getting classic unit
- (nullable TBLRNTClassicUnit *)getClassicUnit:(NSString *)pageId unitId:(NSString *)unitId {
    TBLRNTClassicPage *classicPage = [self getClassicPage:pageId];
    if (!classicPage) {
        NSLog(@"Error: Cannot get classic unit - page not found - pageId: %@, unitId: %@", pageId, unitId);
        return nil;
    }
    
    TBLRNTClassicUnit *tblClassicUnit = [classicPage getClassicUnit:unitId];
    if (!tblClassicUnit) {
        NSLog(@"Error: Classic unit not found - pageId: %@, unitId: %@", pageId, unitId);
    }
    return tblClassicUnit;
}

@end
