#import <Foundation/Foundation.h>

/**
 * StandaloneEventTest - Command line test for event handling logic
 * 
 * This test validates the core event handling concepts without requiring
 * React Native dependencies. It tests the safety mechanisms that prevent
 * crashes from nil/NSNull values.
 */

// Mock the helper methods to test the logic
@interface MockKnotapi : NSObject
@property (nonatomic, assign) BOOL isBridgeActive;
@property (nonatomic, assign) BOOL isClosing;
@property (nonatomic, strong) NSString *productName;
@end

@implementation MockKnotapi

- (instancetype)init {
    self = [super init];
    if (self) {
        _isBridgeActive = YES;
        _isClosing = NO;
    }
    return self;
}

- (BOOL)isBridgeReadyForEvents {
    return self.isBridgeActive && !self.isClosing;
}

- (NSDictionary *)createSafeDictionaryFromDictionary:(NSDictionary *)dictionary {
    if (!dictionary || ![dictionary isKindOfClass:[NSDictionary class]]) {
        return @{};
    }
    
    NSMutableDictionary *safeDictionary = [NSMutableDictionary dictionary];
    for (id key in dictionary) {
        id value = dictionary[key];
        if (key && value && ![key isKindOfClass:[NSNull class]] && ![value isKindOfClass:[NSNull class]]) {
            // If the value is a dictionary, recursively clean it
            if ([value isKindOfClass:[NSDictionary class]]) {
                NSDictionary *cleanedNestedDict = [self createSafeDictionaryFromDictionary:value];
                if (cleanedNestedDict.count > 0) {
                    safeDictionary[key] = cleanedNestedDict;
                }
            } else if ([value isKindOfClass:[NSArray class]]) {
                // If the value is an array, recursively clean it
                NSArray *cleanedArray = [self createSafeArrayFromArray:value];
                if (cleanedArray.count > 0) {
                    safeDictionary[key] = cleanedArray;
                }
            } else {
                safeDictionary[key] = value;
            }
        }
    }
    return [safeDictionary copy];
}

- (NSArray *)createSafeArrayFromArray:(NSArray *)array {
    if (!array || ![array isKindOfClass:[NSArray class]]) {
        return @[];
    }

    NSMutableArray *safeArray = [NSMutableArray array];
    for (id element in array) {
        // Skip NSNull values
        if ([element isKindOfClass:[NSNull class]]) {
            continue;
        }
        
        // If the element is a dictionary, recursively clean it
        if ([element isKindOfClass:[NSDictionary class]]) {
            NSDictionary *cleanedDict = [self createSafeDictionaryFromDictionary:element];
            if (cleanedDict.count > 0) {
                [safeArray addObject:cleanedDict];
            }
        } else if ([element isKindOfClass:[NSArray class]]) {
            // If the element is an array, recursively clean it
            NSArray *cleanedNestedArray = [self createSafeArrayFromArray:element];
            if (cleanedNestedArray.count > 0) {
                [safeArray addObject:cleanedNestedArray];
            }
        } else {
            // Add other valid elements
            [safeArray addObject:element];
        }
    }
    return [safeArray copy];
}

- (void)addSafeStringValue:(NSString *)value forKey:(NSString *)key toDictionary:(NSMutableDictionary *)dictionary {
    if (value && [value isKindOfClass:[NSString class]] && key) {
        dictionary[key] = value;
    }
}

- (void)addSafeMetaData:(NSDictionary *)metaData forKey:(NSString *)key toDictionary:(NSMutableDictionary *)dictionary {
    if (metaData && [metaData isKindOfClass:[NSDictionary class]] && key) {
        NSDictionary *safeMetaData = [self createSafeDictionaryFromDictionary:metaData];
        if (safeMetaData.count > 0) {
            dictionary[key] = safeMetaData;
        }
    }
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"🧪 Starting Standalone Event Test...");
        
        // Test 1: Bridge initialization
        NSLog(@"📋 Test 1: Bridge initialization");
        MockKnotapi *knotapi = [[MockKnotapi alloc] init];
        if (knotapi.isBridgeActive && !knotapi.isClosing) {
            NSLog(@"✅ Bridge initializes correctly (active: %@, closing: %@)", 
                  knotapi.isBridgeActive ? @"YES" : @"NO",
                  knotapi.isClosing ? @"YES" : @"NO");
        } else {
            NSLog(@"❌ Bridge initialization failed");
            return 1;
        }
        
        // Test 2: Bridge state management
        NSLog(@"📋 Test 2: Bridge state management");
        knotapi.isBridgeActive = NO;
        knotapi.isClosing = YES;
        if (![knotapi isBridgeReadyForEvents]) {
            NSLog(@"✅ Bridge correctly reports not ready when inactive and closing");
        } else {
            NSLog(@"❌ Bridge incorrectly reports ready when inactive and closing");
            return 1;
        }
        
        // Test 3: Dictionary safety with valid data
        NSLog(@"📋 Test 3: Dictionary safety with valid data");
        NSDictionary *validDict = @{@"key1": @"value1", @"key2": @"value2"};
        NSDictionary *safeDict = [knotapi createSafeDictionaryFromDictionary:validDict];
        if ([safeDict isEqual:validDict]) {
            NSLog(@"✅ Valid dictionary is returned unchanged");
        } else {
            NSLog(@"❌ Valid dictionary was modified");
            return 1;
        }
        
        // Test 4: Dictionary safety with nil/NSNull values
        NSLog(@"📋 Test 4: Dictionary safety with nil/NSNull values");
        NSMutableDictionary *testDict = [NSMutableDictionary dictionary];
        testDict[@"validKey"] = @"validValue";
        testDict[@"nullKey"] = [NSNull null];
        testDict[@"nilKey"] = nil;
        
        NSDictionary *safeDict2 = [knotapi createSafeDictionaryFromDictionary:testDict];
        if (safeDict2.count == 1 && [safeDict2[@"validKey"] isEqualToString:@"validValue"]) {
            NSLog(@"✅ Dictionary safety correctly filters out nil/NSNull values");
        } else {
            NSLog(@"❌ Dictionary safety failed (count: %lu, expected: 1)", (unsigned long)safeDict2.count);
            return 1;
        }
        
        // Test 5: String safety
        NSLog(@"📋 Test 5: String safety");
        NSMutableDictionary *stringDict = [NSMutableDictionary dictionary];
        [knotapi addSafeStringValue:@"validString" forKey:@"validKey" toDictionary:stringDict];
        [knotapi addSafeStringValue:nil forKey:@"nilKey" toDictionary:stringDict];
        [knotapi addSafeStringValue:(NSString *)[NSNull null] forKey:@"nullKey" toDictionary:stringDict];
        [knotapi addSafeStringValue:(NSString *)@42 forKey:@"numberKey" toDictionary:stringDict];
        [knotapi addSafeStringValue:@"validString2" forKey:nil toDictionary:stringDict];
        
        if (stringDict.count == 1 && [stringDict[@"validKey"] isEqualToString:@"validString"]) {
            NSLog(@"✅ String safety correctly handles nil/NSNull/non-string values");
        } else {
            NSLog(@"❌ String safety failed (count: %lu, expected: 1)", (unsigned long)stringDict.count);
            return 1;
        }
        
        // Test 6: Metadata safety
        NSLog(@"📋 Test 6: Metadata safety");
        NSMutableDictionary *metaDict = [NSMutableDictionary dictionary];
        NSMutableDictionary *testMetaData = [NSMutableDictionary dictionary];
        testMetaData[@"validKey"] = @"validValue";
        testMetaData[@"nullKey"] = [NSNull null];
        testMetaData[@"nilKey"] = nil;
        
        [knotapi addSafeMetaData:testMetaData forKey:@"metaData" toDictionary:metaDict];
        NSDictionary *resultMetaData = metaDict[@"metaData"];
        if (resultMetaData && resultMetaData.count == 1 && [resultMetaData[@"validKey"] isEqualToString:@"validValue"]) {
            NSLog(@"✅ Metadata safety correctly filters out NSNull values");
        } else {
            NSLog(@"❌ Metadata safety failed");
            return 1;
        }
        
        // Test 7: Nil input handling
        NSLog(@"📋 Test 7: Nil input handling");
        NSDictionary *nilDict = [knotapi createSafeDictionaryFromDictionary:nil];
        if (nilDict && nilDict.count == 0) {
            NSLog(@"✅ Nil input handling works correctly");
        } else {
            NSLog(@"❌ Nil input handling failed");
            return 1;
        }
        
        // Test 8: Non-dictionary input handling
        NSLog(@"📋 Test 8: Non-dictionary input handling");
        NSDictionary *nonDict = [knotapi createSafeDictionaryFromDictionary:(NSDictionary *)@"not a dictionary"];
        if (nonDict && nonDict.count == 0) {
            NSLog(@"✅ Non-dictionary input handling works correctly");
        } else {
            NSLog(@"❌ Non-dictionary input handling failed");
            return 1;
        }
        
        // Test 9: Empty metadata handling
        NSLog(@"📋 Test 9: Empty metadata handling");
        NSMutableDictionary *emptyMetaDict = [NSMutableDictionary dictionary];
        [knotapi addSafeMetaData:@{} forKey:@"emptyMeta" toDictionary:emptyMetaDict];
        if (emptyMetaDict.count == 0) {
            NSLog(@"✅ Empty metadata handling works correctly (not added)");
        } else {
            NSLog(@"❌ Empty metadata handling failed");
            return 1;
        }
        
        // Test 10: Bridge state transitions
        NSLog(@"📋 Test 10: Bridge state transitions");
        knotapi.isBridgeActive = YES;
        knotapi.isClosing = NO;
        if ([knotapi isBridgeReadyForEvents]) {
            NSLog(@"✅ Bridge correctly reports ready when active and not closing");
        } else {
            NSLog(@"❌ Bridge incorrectly reports not ready when active and not closing");
            return 1;
        }
        
        // Test 11: Product name setting
        NSLog(@"📋 Test 11: Product name setting");
        knotapi.productName = @"test_product";
        if ([knotapi.productName isEqualToString:@"test_product"]) {
            NSLog(@"✅ Product name setting works correctly");
        } else {
            NSLog(@"❌ Product name setting failed");
            return 1;
        }
        
        // Test 12: Edge case - very large dictionary
        NSLog(@"📋 Test 12: Edge case - large dictionary with mixed data");
        NSMutableDictionary *largeDict = [NSMutableDictionary dictionary];
        for (int i = 0; i < 100; i++) {
            if (i % 3 == 0) {
                largeDict[[NSString stringWithFormat:@"key%d", i]] = [NSString stringWithFormat:@"value%d", i];
            } else if (i % 3 == 1) {
                largeDict[[NSString stringWithFormat:@"key%d", i]] = [NSNull null];
            } else {
                largeDict[[NSString stringWithFormat:@"key%d", i]] = nil;
            }
        }
        
        NSDictionary *largeSafeDict = [knotapi createSafeDictionaryFromDictionary:largeDict];
        if (largeSafeDict.count > 0 && largeSafeDict.count < largeDict.count) {
            NSLog(@"✅ Large dictionary processing works correctly (filtered %lu out of %lu entries)", 
                  (unsigned long)(largeDict.count - largeSafeDict.count), (unsigned long)largeDict.count);
        } else {
            NSLog(@"❌ Large dictionary processing failed");
            return 1;
        }
        
        // Test 13: Special characters in strings
        NSLog(@"📋 Test 13: Special characters in strings");
        NSMutableDictionary *specialDict = [NSMutableDictionary dictionary];
        NSArray *specialStrings = @[
            @"String with spaces",
            @"String\nwith\nnewlines",
            @"String\twith\ttabs",
            @"String with \"quotes\"",
            @"String with 'single quotes'",
            @"String with émojis 🚀",
            @"String with unicode: 你好世界",
            @"String with symbols: !@#$%^&*()",
            @"",
            @"   ",
            @"\n\t\r"
        ];
        
        BOOL allSpecialStringsHandled = YES;
        for (NSString *specialString in specialStrings) {
            NSMutableDictionary *testDict = [NSMutableDictionary dictionary];
            [knotapi addSafeStringValue:specialString forKey:@"specialKey" toDictionary:testDict];
            if (![testDict[@"specialKey"] isEqualToString:specialString]) {
                allSpecialStringsHandled = NO;
                break;
            }
        }
        
        if (allSpecialStringsHandled) {
            NSLog(@"✅ Special characters in strings handled correctly");
        } else {
            NSLog(@"❌ Special characters in strings handling failed");
            return 1;
        }
        
        // Test 14: Nil metadata handling
        NSLog(@"📋 Test 14: Nil metadata handling");
        NSMutableDictionary *nilMetaDict = [NSMutableDictionary dictionary];
        [knotapi addSafeMetaData:nil forKey:@"nilMeta" toDictionary:nilMetaDict];
        if (nilMetaDict.count == 0) {
            NSLog(@"✅ Nil metadata handled correctly (not added)");
        } else {
            NSLog(@"❌ Nil metadata handling failed");
            return 1;
        }
        
        // Test 15: Nested nil values in metadata
        NSLog(@"📋 Test 15: Nested nil values in metadata");
        NSMutableDictionary *nestedNilMeta = [NSMutableDictionary dictionary];
        nestedNilMeta[@"validKey"] = @"validValue";
        nestedNilMeta[@"nilValue"] = nil;
        nestedNilMeta[@"nullValue"] = [NSNull null];
        
        // Create nested dictionary with nil values
        NSMutableDictionary *nestedDict = [NSMutableDictionary dictionary];
        nestedDict[@"innerValid"] = @"innerValue";
        nestedDict[@"innerNil"] = nil;
        nestedDict[@"innerNull"] = [NSNull null];
        nestedNilMeta[@"nestedDict"] = nestedDict;
        
        // Create array with NSNull values (nil cannot be added to arrays)
        NSMutableArray *nestedArray = [NSMutableArray array];
        [nestedArray addObject:@"arrayValue"];
        [nestedArray addObject:[NSNull null]]; // Use NSNull instead of nil
        [nestedArray addObject:[NSNull null]];
        [nestedArray addObject:@"anotherValue"];
        nestedNilMeta[@"nestedArray"] = nestedArray;
        
        NSMutableDictionary *nestedMetaDict = [NSMutableDictionary dictionary];
        [knotapi addSafeMetaData:nestedNilMeta forKey:@"nestedMeta" toDictionary:nestedMetaDict];
        
        NSDictionary *resultNestedMeta = nestedMetaDict[@"nestedMeta"];
        if (resultNestedMeta && resultNestedMeta.count == 3 && 
            [resultNestedMeta[@"validKey"] isEqualToString:@"validValue"] &&
            resultNestedMeta[@"nestedDict"] != nil &&
            resultNestedMeta[@"nestedArray"] != nil) {
            
            // Verify that the nested array has NSNull values filtered out
            NSArray *filteredArray = resultNestedMeta[@"nestedArray"];
            if (filteredArray.count == 2 && 
                [filteredArray[0] isEqualToString:@"arrayValue"] &&
                [filteredArray[1] isEqualToString:@"anotherValue"]) {
                NSLog(@"✅ Nested nil values in metadata handled correctly (array NSNull filtered)");
            } else {
                NSLog(@"❌ Array NSNull filtering failed (count: %lu, expected: 2)", (unsigned long)filteredArray.count);
                return 1;
            }
        } else {
            NSLog(@"❌ Nested nil values in metadata handling failed");
            return 1;
        }
        
        // Test 16: Deeply nested nil values
        NSLog(@"📋 Test 16: Deeply nested nil values");
        NSMutableDictionary *deepNestedMeta = [NSMutableDictionary dictionary];
        
        // Create level3 dictionary
        NSMutableDictionary *level3 = [NSMutableDictionary dictionary];
        level3[@"valid"] = @"value";
        level3[@"nil"] = nil;
        level3[@"null"] = [NSNull null];
        
        // Create level2 dictionary
        NSMutableDictionary *level2 = [NSMutableDictionary dictionary];
        level2[@"level3"] = level3;
        level2[@"level2nil"] = nil;
        level2[@"level2null"] = [NSNull null];
        
        // Create level1 dictionary
        NSMutableDictionary *level1 = [NSMutableDictionary dictionary];
        level1[@"level2"] = level2;
        level1[@"level1nil"] = nil;
        level1[@"level1null"] = [NSNull null];
        
        deepNestedMeta[@"level1"] = level1;
        
        NSMutableDictionary *deepMetaDict = [NSMutableDictionary dictionary];
        [knotapi addSafeMetaData:deepNestedMeta forKey:@"deepMeta" toDictionary:deepMetaDict];
        
        NSDictionary *resultDeepMeta = deepMetaDict[@"deepMeta"];
        if (resultDeepMeta && resultDeepMeta.count == 1 && resultDeepMeta[@"level1"] != nil) {
            NSLog(@"✅ Deeply nested nil values handled correctly");
        } else {
            NSLog(@"❌ Deeply nested nil values handling failed");
            return 1;
        }
        
        // Test 17: Metadata with only nil/NSNull values
        NSLog(@"📋 Test 17: Metadata with only nil/NSNull values");
        NSMutableDictionary *allNilMeta = [NSMutableDictionary dictionary];
        allNilMeta[@"nil1"] = nil;
        allNilMeta[@"null1"] = [NSNull null];
        allNilMeta[@"nil2"] = nil;
        allNilMeta[@"null2"] = [NSNull null];
        
        NSMutableDictionary *allNilMetaDict = [NSMutableDictionary dictionary];
        [knotapi addSafeMetaData:allNilMeta forKey:@"allNilMeta" toDictionary:allNilMetaDict];
        
        if (allNilMetaDict.count == 0) {
            NSLog(@"✅ Metadata with only nil/NSNull values handled correctly (not added)");
        } else {
            NSLog(@"❌ Metadata with only nil/NSNull values handling failed");
            return 1;
        }
        
        NSLog(@"");
        NSLog(@"🎉 All Standalone Event Tests Passed!");
        NSLog(@"");
        NSLog(@"📊 Test Summary:");
        NSLog(@"   ✅ Bridge initialization");
        NSLog(@"   ✅ Bridge state management");
        NSLog(@"   ✅ Dictionary safety (valid data)");
        NSLog(@"   ✅ Dictionary safety (nil/NSNull filtering)");
        NSLog(@"   ✅ String safety");
        NSLog(@"   ✅ Metadata safety");
        NSLog(@"   ✅ Nil input handling");
        NSLog(@"   ✅ Non-dictionary input handling");
        NSLog(@"   ✅ Empty metadata handling");
        NSLog(@"   ✅ Bridge state transitions");
        NSLog(@"   ✅ Product name setting");
        NSLog(@"   ✅ Large dictionary processing");
        NSLog(@"   ✅ Special characters handling");
        NSLog(@"   ✅ Nil metadata handling");
        NSLog(@"   ✅ Nested nil values in metadata");
        NSLog(@"   ✅ Deeply nested nil values");
        NSLog(@"   ✅ Metadata with only nil/NSNull values");
        NSLog(@"");
        NSLog(@"🔧 Event handling logic is working correctly!");
        NSLog(@"🛡️  Safety mechanisms prevent crashes from nil/NSNull values");
        NSLog(@"📱 Ready for React Native integration");
        
        return 0;
    }
}
