#import "HealthKitBridge.h"
#import <Foundation/Foundation.h>
#import <HealthKit/HealthKit.h>
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
#import <React/RCTUtils.h>
#import <React/RCTLog.h>

@interface HealthKitBridge ()

@property (nonatomic) HKHealthStore *healthStore;
@property (nonatomic, assign) BOOL hasListeners;
@property (nonatomic, strong) NSMutableDictionary *observers;

@end

@implementation HealthKitBridge

RCT_EXPORT_MODULE()

+ (BOOL)requiresMainQueueSetup {
    return NO;
}

- (NSDictionary *)constantsToExport {
    return @{
        @"version": @"1.4.10",
        @"isHealthKitAvailableOnDevice": @([HKHealthStore isHealthDataAvailable])
    };
}

- (NSArray<NSString *> *)supportedEvents {
    return @[
        @"healthKitDataChanged",
        @"authorizationChanged",
        @"stepCountChanged",
        @"heartRateChanged",
        @"workoutChanged",
        @"sleepAnalysisChanged"
    ];
}

- (instancetype)init {
    self = [super init];
    if (self) {
        NSLog(@"🔐 [Native] Inicializando HealthKitBridge...");
        self.healthStore = [[HKHealthStore alloc] init];
        NSLog(@"🔐 [Native] HealthStore criado: %@", self.healthStore ? @"SUCCESS" : @"FAILED");
        self.hasListeners = NO;
        self.observers = [[NSMutableDictionary alloc] init];
        NSLog(@"🔐 [Native] HealthKitBridge inicializado com sucesso");
    }
    return self;
}

- (void)startObserving {
    self.hasListeners = YES;
}

- (void)stopObserving {
    self.hasListeners = NO;
    [self stopAllObservers];
}

// MARK: - Availability and Permissions

RCT_EXPORT_METHOD(isHealthKitAvailable:(RCTResponseSenderBlock)callback) {
    BOOL isAvailable = [HKHealthStore isHealthDataAvailable];
    callback(@[[NSNull null], @(isAvailable)]);
}

RCT_EXPORT_METHOD(checkAvailability:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    BOOL isAvailable = [HKHealthStore isHealthDataAvailable];
    resolve(@(isAvailable));
}

RCT_EXPORT_METHOD(requestAuthorization:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    if (![HKHealthStore isHealthDataAvailable]) {
        reject(@"ERR_HEALTHKIT_UNAVAILABLE", @"HealthKit is not available on this device", nil);
        return;
    }
    
    NSSet *typesToRead = [self getAllReadTypes];
    NSSet *typesToWrite = [self getAllWriteTypes];
    
    // Ensure we're on the main thread for authorization requests
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.healthStore requestAuthorizationToShareTypes:typesToWrite
                                                 readTypes:typesToRead
                                                completion:^(BOOL success, NSError *error) {
            if (success) {
                resolve(@(YES));
            } else {
                NSString *errorMessage = error ? error.localizedDescription : @"Failed to authorize HealthKit";
                reject(@"ERR_AUTHORIZATION", errorMessage, error);
            }
        }];
    });
}

RCT_EXPORT_METHOD(requestReadOnlyAuthorization:(NSArray *)readTypes
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    NSLog(@"📖 [Native] requestReadOnlyAuthorization iniciado");
    NSLog(@"📖 [Native] iOS Version: %@", [[UIDevice currentDevice] systemVersion]);
    NSLog(@"📖 [Native] HealthKit Available: %@", [HKHealthStore isHealthDataAvailable] ? @"YES" : @"NO");
    
    // Verificar estado do app
    UIApplicationState appState = [[UIApplication sharedApplication] applicationState];
    NSString *appStateString;
    switch (appState) {
        case UIApplicationStateActive:
            appStateString = @"Active";
            break;
        case UIApplicationStateInactive:
            appStateString = @"Inactive";
            break;
        case UIApplicationStateBackground:
            appStateString = @"Background";
            break;
        default:
            appStateString = @"Unknown";
            break;
    }
    NSLog(@"📖 [Native] App State: %@", appStateString);
    
    if (appState != UIApplicationStateActive) {
        NSLog(@"❌ [Native] App não está ativo, estado: %@", appStateString);
        reject(@"ERR_APP_STATE", @"App must be active to request authorization", nil);
        return;
    }
    
    if (![HKHealthStore isHealthDataAvailable]) {
        NSLog(@"❌ [Native] HealthKit não disponível");
        reject(@"ERR_HEALTHKIT_UNAVAILABLE", @"HealthKit is not available on this device", nil);
        return;
    }
    
    if (!readTypes || ![readTypes isKindOfClass:[NSArray class]]) {
        NSLog(@"❌ [Native] readTypes inválido");
        reject(@"ERR_INVALID_INPUT", @"Invalid readTypes array", nil);
        return;
    }
    
    NSLog(@"📖 [Native] readTypes: %@", readTypes);
    
    NSMutableSet *typesToRead = [[NSMutableSet alloc] init];
    NSMutableArray *failedReadTypes = [[NSMutableArray alloc] init];
    
    for (NSString *identifier in readTypes) {
        if (![identifier isKindOfClass:[NSString class]] || identifier.length == 0) {
            [failedReadTypes addObject:identifier ?: @"null"];
            continue;
        }
        
        NSLog(@"🔍 [Native] Processando readType: %@", identifier);
        
        @try {
            HKObjectType *type = [self getHKObjectTypeFromString:identifier];
            if (type) {
                NSLog(@"✅ [Native] Tipo reconhecido: %@", type.identifier);
                [typesToRead addObject:type];
            } else {
                NSLog(@"❌ [Native] Tipo não reconhecido: %@", identifier);
                [failedReadTypes addObject:identifier];
            }
        } @catch (NSException *exception) {
            NSLog(@"❌ [Native] Exception ao processar tipo %@: %@", identifier, exception.reason);
            [failedReadTypes addObject:identifier];
        }
    }
    
    // Log failed types for debugging
    if (failedReadTypes.count > 0) {
        NSLog(@"Failed to process read types: %@", [failedReadTypes componentsJoinedByString:@", "]);
    }
    
    // If no valid types to request, return success
    if (typesToRead.count == 0) {
        NSLog(@"⚠️ [Native] Nenhum tipo válido para autorizar");
        resolve(@(YES));
        return;
    }
    
    NSLog(@"📖 [Native] Tipos válidos para autorizar: %@", typesToRead);
    
    // Check current authorization status before requesting
    NSMutableSet *typesNeedingAuthorization = [[NSMutableSet alloc] init];
    for (HKObjectType *type in typesToRead) {
        HKAuthorizationStatus currentStatus = [self.healthStore authorizationStatusForType:type];
        NSLog(@"🔍 [Native] %@ - Status atual: %ld", type.identifier, (long)currentStatus);
        
        if (currentStatus == HKAuthorizationStatusNotDetermined) {
            [typesNeedingAuthorization addObject:type];
            NSLog(@"📖 [Native] %@ precisa de autorização", type.identifier);
        } else if (currentStatus == HKAuthorizationStatusSharingAuthorized) {
            NSLog(@"✅ [Native] %@ já autorizado", type.identifier);
        } else {
            NSLog(@"❌ [Native] %@ negado ou restrito", type.identifier);
        }
    }
    
    // If no types need authorization, return success
    if (typesNeedingAuthorization.count == 0) {
        NSLog(@"✅ [Native] Todos os tipos já estão autorizados");
        resolve(@(YES));
        return;
    }
    
    NSLog(@"📖 [Native] Tipos que precisam de autorização: %@", typesNeedingAuthorization);
    
    // Ensure we're on the main thread for authorization requests
    if ([NSThread isMainThread]) {
        NSLog(@"📖 [Native] Executando na main thread");
        @try {
            NSLog(@"📖 [Native] Chamando requestAuthorizationToShareTypes (apenas leitura)...");
            NSLog(@"📖 [Native] writeTypes: [NSSet set] (vazio)");
            NSLog(@"📖 [Native] readTypes count: %lu", (unsigned long)typesNeedingAuthorization.count);
            
            // Pass empty set for write types to request read-only access
            [self.healthStore requestAuthorizationToShareTypes:[NSSet set]
                                                     readTypes:typesNeedingAuthorization
                                                    completion:^(BOOL success, NSError *error) {
                if (success) {
                    NSLog(@"✅ [Native] Autorização de leitura bem-sucedida");
                    resolve(@(YES));
                } else {
                    NSLog(@"❌ [Native] Autorização de leitura falhou: %@", error.localizedDescription);
                    
                    // Check if this is a common iOS limitation where write permission is required
                    if (error && [error.localizedDescription containsString:@"sharing"]) {
                        NSLog(@"⚠️ [Native] iOS pode estar exigindo permissão de escrita para leitura");
                        NSLog(@"⚠️ [Native] Tentando com permissão de escrita mínima...");
                        
                        // Try with minimal write permissions (same as read types)
                        [self.healthStore requestAuthorizationToShareTypes:typesToRead
                                                                 readTypes:typesToRead
                                                                completion:^(BOOL retrySuccess, NSError *retryError) {
                            if (retrySuccess) {
                                NSLog(@"✅ [Native] Autorização com escrita mínima bem-sucedida");
                                resolve(@(YES));
                            } else {
                                NSLog(@"❌ [Native] Retry também falhou: %@", retryError.localizedDescription);
                                NSString *errorMessage = retryError ? retryError.localizedDescription : @"Failed to authorize HealthKit for reading";
                                reject(@"ERR_AUTHORIZATION_FAILED", errorMessage, retryError);
                            }
                        }];
                    } else {
                        NSString *errorMessage = error ? error.localizedDescription : @"Failed to authorize HealthKit for reading";
                        reject(@"ERR_AUTHORIZATION_FAILED", errorMessage, error);
                    }
                }
            }];
        } @catch (NSException *exception) {
            NSLog(@"❌ [Native] Exception durante autorização: %@", exception.reason);
            reject(@"ERR_AUTHORIZATION_EXCEPTION", exception.reason, nil);
        }
    } else {
        NSLog(@"📖 [Native] Despachando para main thread");
        dispatch_async(dispatch_get_main_queue(), ^{
            @try {
                NSLog(@"📖 [Native] Chamando requestAuthorizationToShareTypes (apenas leitura) na main thread...");
                NSLog(@"📖 [Native] writeTypes: nil (vazio)");
                NSLog(@"📖 [Native] readTypes count: %lu", (unsigned long)typesNeedingAuthorization.count);
                
                // Pass empty set for write types to request read-only access
                [self.healthStore requestAuthorizationToShareTypes:[NSSet set]
                                                         readTypes:typesNeedingAuthorization
                                                        completion:^(BOOL success, NSError *error) {
                    if (success) {
                        NSLog(@"✅ [Native] Autorização de leitura bem-sucedida");
                        resolve(@(YES));
                    } else {
                        NSLog(@"❌ [Native] Autorização de leitura falhou: %@", error.localizedDescription);
                        
                        // Check if this is a common iOS limitation where write permission is required
                        if (error && [error.localizedDescription containsString:@"sharing"]) {
                            NSLog(@"⚠️ [Native] iOS pode estar exigindo permissão de escrita para leitura");
                            NSLog(@"⚠️ [Native] Tentando com permissão de escrita mínima...");
                            
                            // Try with minimal write permissions (same as read types)
                            [self.healthStore requestAuthorizationToShareTypes:typesToRead
                                                                     readTypes:typesToRead
                                                                    completion:^(BOOL retrySuccess, NSError *retryError) {
                                if (retrySuccess) {
                                    NSLog(@"✅ [Native] Autorização com escrita mínima bem-sucedida");
                                    resolve(@(YES));
                                } else {
                                    NSLog(@"❌ [Native] Retry também falhou: %@", retryError.localizedDescription);
                                    NSString *errorMessage = retryError ? retryError.localizedDescription : @"Failed to authorize HealthKit for reading";
                                    reject(@"ERR_AUTHORIZATION_FAILED", errorMessage, retryError);
                                }
                            }];
                        } else {
                            NSString *errorMessage = error ? error.localizedDescription : @"Failed to authorize HealthKit for reading";
                            reject(@"ERR_AUTHORIZATION_FAILED", errorMessage, error);
                        }
                    }
                }];
            } @catch (NSException *exception) {
                NSLog(@"❌ [Native] Exception durante autorização: %@", exception.reason);
                reject(@"ERR_AUTHORIZATION_EXCEPTION", exception.reason, nil);
            }
        });
    }
}

RCT_EXPORT_METHOD(requestSelectiveAuthorization:(NSArray *)readTypes
                  writeTypes:(NSArray *)writeTypes
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    NSLog(@"🔐 [Native] requestSelectiveAuthorization iniciado");
    NSLog(@"🔐 [Native] iOS Version: %@", [[UIDevice currentDevice] systemVersion]);
    NSLog(@"🔐 [Native] HealthKit Available: %@", [HKHealthStore isHealthDataAvailable] ? @"YES" : @"NO");
    
    // Verificar estado do app
    UIApplicationState appState = [[UIApplication sharedApplication] applicationState];
    NSString *appStateString;
    switch (appState) {
        case UIApplicationStateActive:
            appStateString = @"Active";
            break;
        case UIApplicationStateInactive:
            appStateString = @"Inactive";
            break;
        case UIApplicationStateBackground:
            appStateString = @"Background";
            break;
        default:
            appStateString = @"Unknown";
            break;
    }
    NSLog(@"🔐 [Native] App State: %@", appStateString);
    
    if (appState != UIApplicationStateActive) {
        NSLog(@"❌ [Native] App não está ativo, estado: %@", appStateString);
        reject(@"ERR_APP_STATE", @"App must be active to request authorization", nil);
        return;
    }
    
    if (![HKHealthStore isHealthDataAvailable]) {
        NSLog(@"❌ [Native] HealthKit não disponível");
        reject(@"ERR_HEALTHKIT_UNAVAILABLE", @"HealthKit is not available on this device", nil);
        return;
    }
    
    if (!readTypes || ![readTypes isKindOfClass:[NSArray class]]) {
        NSLog(@"❌ [Native] readTypes inválido");
        reject(@"ERR_INVALID_INPUT", @"Invalid readTypes array", nil);
        return;
    }
    
    if (!writeTypes || ![writeTypes isKindOfClass:[NSArray class]]) {
        NSLog(@"❌ [Native] writeTypes inválido");
        reject(@"ERR_INVALID_INPUT", @"Invalid writeTypes array", nil);
        return;
    }
    
    NSLog(@"🔐 [Native] readTypes: %@", readTypes);
    NSLog(@"🔐 [Native] writeTypes: %@", writeTypes);
    
    NSMutableSet *typesToRead = [[NSMutableSet alloc] init];
    NSMutableSet *typesToWrite = [[NSMutableSet alloc] init];
    NSMutableArray *failedReadTypes = [[NSMutableArray alloc] init];
    NSMutableArray *failedWriteTypes = [[NSMutableArray alloc] init];
    
    for (NSString *identifier in readTypes) {
        if (![identifier isKindOfClass:[NSString class]] || identifier.length == 0) {
            [failedReadTypes addObject:identifier ?: @"null"];
            continue;
        }
        
        NSLog(@"🔍 [Native] Processando readType: %@", identifier);
        
        @try {
            HKObjectType *type = [self getHKObjectTypeFromString:identifier];
            if (type) {
                NSLog(@"✅ [Native] Tipo reconhecido: %@", type.identifier);
                [typesToRead addObject:type];
            } else {
                NSLog(@"❌ [Native] Tipo não reconhecido: %@", identifier);
                [failedReadTypes addObject:identifier];
            }
        } @catch (NSException *exception) {
            NSLog(@"❌ [Native] Exception ao processar tipo %@: %@", identifier, exception.reason);
            [failedReadTypes addObject:identifier];
        }
    }
    
    for (NSString *identifier in writeTypes) {
        if (![identifier isKindOfClass:[NSString class]] || identifier.length == 0) {
            [failedWriteTypes addObject:identifier ?: @"null"];
            continue;
        }
        
        @try {
            HKSampleType *type = [self getHKSampleTypeFromString:identifier];
            if (type) {
                [typesToWrite addObject:type];
            } else {
                [failedWriteTypes addObject:identifier];
            }
        } @catch (NSException *exception) {
            [failedWriteTypes addObject:identifier];
        }
    }
    
    // Log failed types for debugging
    if (failedReadTypes.count > 0) {
        NSLog(@"Failed to process read types: %@", [failedReadTypes componentsJoinedByString:@", "]);
    }
    if (failedWriteTypes.count > 0) {
        NSLog(@"Failed to process write types: %@", [failedWriteTypes componentsJoinedByString:@", "]);
    }
    
    // If no valid types to request, return success
    if (typesToRead.count == 0 && typesToWrite.count == 0) {
        resolve(@(YES));
        return;
    }
    
    // Ensure we're on the main thread for authorization requests
    if ([NSThread isMainThread]) {
        NSLog(@"🔐 [Native] Executando na main thread");
        @try {
            NSLog(@"🔐 [Native] Chamando requestAuthorizationToShareTypes...");
            [self.healthStore requestAuthorizationToShareTypes:typesToWrite
                                                     readTypes:typesToRead
                                                    completion:^(BOOL success, NSError *error) {
                if (success) {
                    NSLog(@"✅ [Native] Autorização bem-sucedida");
                    resolve(@(YES));
                } else {
                    NSLog(@"❌ [Native] Autorização falhou: %@", error.localizedDescription);
                    NSString *errorMessage = error ? error.localizedDescription : @"Failed to authorize HealthKit";
                    reject(@"ERR_AUTHORIZATION", errorMessage, error);
                }
            }];
        } @catch (NSException *exception) {
            NSLog(@"❌ [Native] Exception capturada: %@", exception.reason);
            NSLog(@"❌ [Native] Exception name: %@", exception.name);
            NSLog(@"❌ [Native] Exception userInfo: %@", exception.userInfo);
            reject(@"ERR_AUTHORIZATION", @"Property is not configurable", nil);
        }
    } else {
        NSLog(@"🔐 [Native] Executando em background, movendo para main thread");
        dispatch_async(dispatch_get_main_queue(), ^{
            @try {
                NSLog(@"🔐 [Native] Chamando requestAuthorizationToShareTypes na main thread...");
                [self.healthStore requestAuthorizationToShareTypes:typesToWrite
                                                         readTypes:typesToRead
                                                        completion:^(BOOL success, NSError *error) {
                    if (success) {
                        NSLog(@"✅ [Native] Autorização bem-sucedida (main thread)");
                        resolve(@(YES));
                    } else {
                        NSLog(@"❌ [Native] Autorização falhou (main thread): %@", error.localizedDescription);
                        NSString *errorMessage = error ? error.localizedDescription : @"Failed to authorize HealthKit";
                        reject(@"ERR_AUTHORIZATION", errorMessage, error);
                    }
                }];
            } @catch (NSException *exception) {
                NSLog(@"❌ [Native] Exception capturada (main thread): %@", exception.reason);
                NSLog(@"❌ [Native] Exception name: %@", exception.name);
                NSLog(@"❌ [Native] Exception userInfo: %@", exception.userInfo);
                reject(@"ERR_AUTHORIZATION", @"Property is not configurable", nil);
            }
        });
    }
}

RCT_EXPORT_METHOD(getAuthorizationStatus:(NSArray *)identifiers
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    NSLog(@"🔍 [Native] getAuthorizationStatus iniciado");
    NSLog(@"🔍 [Native] identifiers: %@", identifiers);
    
    if (![HKHealthStore isHealthDataAvailable]) {
        NSLog(@"❌ [Native] HealthKit não disponível");
        reject(@"ERR_HEALTHKIT_UNAVAILABLE", @"HealthKit is not available on this device", nil);
        return;
    }
    
    if (!identifiers || ![identifiers isKindOfClass:[NSArray class]] || identifiers.count == 0) {
        NSLog(@"❌ [Native] identifiers inválido ou vazio");
        reject(@"ERR_INVALID_INPUT", @"Invalid or empty identifiers array", nil);
        return;
    }
    
    NSMutableArray *statusArray = [[NSMutableArray alloc] init];
    NSMutableArray *failedIdentifiers = [[NSMutableArray alloc] init];
    
    for (NSString *identifier in identifiers) {
        if (![identifier isKindOfClass:[NSString class]] || identifier.length == 0) {
            NSLog(@"❌ [Native] identifier inválido: %@", identifier);
            [failedIdentifiers addObject:identifier ?: @"null"];
            continue;
        }
        
        NSLog(@"🔍 [Native] Processando identifier: %@", identifier);
        
        @try {
            HKObjectType *type = [self getHKObjectTypeFromString:identifier];
            
            if (type) {
                HKAuthorizationStatus status = [self.healthStore authorizationStatusForType:type];
                NSString *statusString = [self authorizationStatusToString:status];
                
                NSLog(@"🔍 [Native] %@ - Status: %ld (%@)", identifier, (long)status, statusString);
                
                NSDictionary *statusDict = @{
                    @"identifier": identifier,
                    @"status": statusString
                };
                [statusArray addObject:statusDict];
            } else {
                NSLog(@"❌ [Native] Tipo não reconhecido: %@", identifier);
                [failedIdentifiers addObject:identifier];
            }
        } @catch (NSException *exception) {
            NSLog(@"❌ [Native] Exception ao processar %@: %@", identifier, exception.reason);
            [failedIdentifiers addObject:identifier];
        }
    }
    
    NSLog(@"🔍 [Native] Status array: %@", statusArray);
    NSLog(@"🔍 [Native] Failed identifiers: %@", failedIdentifiers);
    
    if (failedIdentifiers.count > 0) {
        NSString *errorMessage = [NSString stringWithFormat:@"Failed to process identifiers: %@", [failedIdentifiers componentsJoinedByString:@", "]];
        NSLog(@"❌ [Native] Erro: %@", errorMessage);
        reject(@"ERR_INVALID_IDENTIFIERS", errorMessage, nil);
        return;
    }
    
    NSLog(@"✅ [Native] getAuthorizationStatus concluído com sucesso");
    resolve(statusArray);
}

RCT_EXPORT_METHOD(getTypeInfo:(NSString *)identifier
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    if (!identifier || ![identifier isKindOfClass:[NSString class]] || identifier.length == 0) {
        reject(@"ERR_INVALID_INPUT", @"Invalid identifier provided", nil);
        return;
    }
    
    HKObjectType *type = [self getHKObjectTypeFromString:identifier];
    
    if (type) {
        NSString *name = [type identifier];
        NSString *category = @"unknown";
        NSString *typeString = @"unknown";
        
        if ([type isKindOfClass:[HKQuantityType class]]) {
            typeString = @"quantity";
            if ([name containsString:@"Step"]) {
                category = @"activity";
            } else if ([name containsString:@"Heart"]) {
                category = @"heart";
            } else if ([name containsString:@"Energy"]) {
                category = @"activity";
            } else if ([name containsString:@"Distance"]) {
                category = @"activity";
            } else if ([name containsString:@"Exercise"]) {
                category = @"activity";
            } else if ([name containsString:@"Height"] || [name containsString:@"Weight"] || [name containsString:@"Body"]) {
                category = @"body";
            } else if ([name containsString:@"Blood"]) {
                category = @"vitals";
            } else if ([name containsString:@"Glucose"]) {
                category = @"lab";
            }
        } else if ([type isKindOfClass:[HKCategoryType class]]) {
            typeString = @"category";
            if ([name containsString:@"Sleep"]) {
                category = @"sleep";
            } else if ([name containsString:@"Mindful"]) {
                category = @"mindfulness";
            } else if ([name containsString:@"Stand"]) {
                category = @"activity";
            } else if ([name containsString:@"Menstrual"] || [name containsString:@"Sexual"] || [name containsString:@"Cervical"]) {
                category = @"reproductive";
            }
        } else if ([type isKindOfClass:[HKWorkoutType class]]) {
            typeString = @"workout";
            category = @"workouts";
        }
        
        NSDictionary *typeInfo = @{
            @"identifier": identifier,
            @"name": name,
            @"category": category,
            @"type": typeString
        };
        
        resolve(typeInfo);
    } else {
        reject(@"ERR_INVALID_TYPE", @"Invalid type identifier", nil);
    }
}

// MARK: - Data Reading

RCT_EXPORT_METHOD(getQuantitySamplesForDays:(NSString *)identifier
                  unit:(NSString *)unit
                  days:(nonnull NSNumber *)days
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    if (![HKHealthStore isHealthDataAvailable]) {
        reject(@"ERR_HEALTHKIT_UNAVAILABLE", @"HealthKit is not available on this device", nil);
        return;
    }
    
    if (!identifier || ![identifier isKindOfClass:[NSString class]] || identifier.length == 0) {
        reject(@"ERR_INVALID_INPUT", @"Invalid identifier provided", nil);
        return;
    }
    
    if (!unit || ![unit isKindOfClass:[NSString class]] || unit.length == 0) {
        reject(@"ERR_INVALID_INPUT", @"Invalid unit provided", nil);
        return;
    }
    
    if (!days || ![days isKindOfClass:[NSNumber class]] || days.intValue <= 0 || days.intValue > 365) {
        reject(@"ERR_INVALID_INPUT", @"Invalid days value (must be between 1 and 365)", nil);
        return;
    }
    
    HKQuantityType *quantityType = [HKQuantityType quantityTypeForIdentifier:identifier];
    if (!quantityType) {
        reject(@"ERR_INVALID_TYPE", @"Invalid quantity type", nil);
        return;
    }
    
    HKUnit *hkUnit = [self unitFromString:unit];
    if (!hkUnit) {
        reject(@"ERR_INVALID_UNIT", @"Invalid unit", nil);
        return;
    }
    
    NSDate *endDate = [NSDate date];
    NSDate *startDate = [NSDate dateWithTimeInterval:-(days.intValue * 24 * 60 * 60) sinceDate:endDate];
    
    NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionStrictStartDate];
    
    HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:quantityType
                                                           predicate:predicate
                                                               limit:HKObjectQueryNoLimit
                                                     sortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:YES]]
                                                      resultsHandler:^(HKSampleQuery *query, NSArray *samples, NSError *error) {
        if (error) {
            reject(@"ERR_QUERY", @"Error querying data", error);
            return;
        }
        
        NSMutableArray *results = [[NSMutableArray alloc] init];
        for (HKQuantitySample *sample in samples) {
            double value = [sample.quantity doubleValueForUnit:hkUnit];
            NSDictionary *sampleDict = @{
                @"value": @(value),
                @"startDate": [self dateToISO8601String:sample.startDate],
                @"endDate": [self dateToISO8601String:sample.endDate],
                @"uuid": sample.UUID.UUIDString,
                @"sourceRevision": [self sourceRevisionToDict:sample.sourceRevision]
            };
            [results addObject:sampleDict];
        }
        
        resolve(results);
    }];
    
    [self.healthStore executeQuery:query];
}

RCT_EXPORT_METHOD(getQuantitySamplesForHours:(NSString *)identifier
                  unit:(NSString *)unit
                  hours:(nonnull NSNumber *)hours
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    HKQuantityType *quantityType = [HKQuantityType quantityTypeForIdentifier:identifier];
    if (!quantityType) {
        reject(@"ERR_INVALID_TYPE", @"Invalid quantity type", nil);
        return;
    }
    
    HKUnit *hkUnit = [self unitFromString:unit];
    if (!hkUnit) {
        reject(@"ERR_INVALID_UNIT", @"Invalid unit", nil);
        return;
    }
    
    NSDate *endDate = [NSDate date];
    NSDate *startDate = [NSDate dateWithTimeInterval:-(hours.intValue * 60 * 60) sinceDate:endDate];
    
    NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionStrictStartDate];
    
    HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:quantityType
                                                           predicate:predicate
                                                               limit:HKObjectQueryNoLimit
                                                     sortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:YES]]
                                                      resultsHandler:^(HKSampleQuery *query, NSArray *samples, NSError *error) {
        if (error) {
            reject(@"ERR_QUERY", @"Error querying data", error);
            return;
        }
        
        NSMutableArray *results = [[NSMutableArray alloc] init];
        for (HKQuantitySample *sample in samples) {
            double value = [sample.quantity doubleValueForUnit:hkUnit];
            NSDictionary *sampleDict = @{
                @"value": @(value),
                @"startDate": [self dateToISO8601String:sample.startDate],
                @"endDate": [self dateToISO8601String:sample.endDate],
                @"uuid": sample.UUID.UUIDString,
                @"sourceRevision": [self sourceRevisionToDict:sample.sourceRevision]
            };
            [results addObject:sampleDict];
        }
        
        resolve(results);
    }];
    
    [self.healthStore executeQuery:query];
}

RCT_EXPORT_METHOD(getQuantitySamplesForLastDayWithData:(NSString *)identifier
                  unit:(NSString *)unit
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    HKQuantityType *quantityType = [HKQuantityType quantityTypeForIdentifier:identifier];
    if (!quantityType) {
        reject(@"ERR_INVALID_TYPE", @"Invalid quantity type", nil);
        return;
    }
    
    HKUnit *hkUnit = [self unitFromString:unit];
    if (!hkUnit) {
        reject(@"ERR_INVALID_UNIT", @"Invalid unit", nil);
        return;
    }
    
    NSDate *endDate = [NSDate date];
    NSDate *startDate = [NSDate dateWithTimeInterval:-(30 * 24 * 60 * 60) sinceDate:endDate]; // Search in last 30 days
    
    NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionStrictStartDate];
    
    HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:quantityType
                                                           predicate:predicate
                                                               limit:HKObjectQueryNoLimit
                                                     sortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO]]
                                                      resultsHandler:^(HKSampleQuery *query, NSArray *samples, NSError *error) {
        if (error) {
            reject(@"ERR_QUERY", @"Error querying data", error);
            return;
        }
        
        if (samples.count == 0) {
            resolve(@[]);
            return;
        }
        
        HKQuantitySample *lastSample = samples.firstObject;
        NSDate *lastSampleDate = lastSample.startDate;
        
        NSCalendar *calendar = [NSCalendar currentCalendar];
        NSDateComponents *components = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:lastSampleDate];
        
        NSDate *dayStart = [calendar dateFromComponents:components];
        NSDate *dayEnd = [calendar dateByAddingUnit:NSCalendarUnitDay value:1 toDate:dayStart options:0];
        
        NSPredicate *dayPredicate = [HKQuery predicateForSamplesWithStartDate:dayStart endDate:dayEnd options:HKQueryOptionStrictStartDate];
        
        HKSampleQuery *dayQuery = [[HKSampleQuery alloc] initWithSampleType:quantityType
                                                                   predicate:dayPredicate
                                                                       limit:HKObjectQueryNoLimit
                                                             sortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:YES]]
                                                              resultsHandler:^(HKSampleQuery *query, NSArray *daySamples, NSError *error) {
            if (error) {
                reject(@"ERR_QUERY", @"Error querying day data", error);
                return;
            }
            
            NSMutableArray *results = [[NSMutableArray alloc] init];
            for (HKQuantitySample *sample in daySamples) {
                double value = [sample.quantity doubleValueForUnit:hkUnit];
                NSDictionary *sampleDict = @{
                    @"value": @(value),
                    @"startDate": [self dateToISO8601String:sample.startDate],
                    @"endDate": [self dateToISO8601String:sample.endDate],
                    @"uuid": sample.UUID.UUIDString,
                    @"sourceRevision": [self sourceRevisionToDict:sample.sourceRevision]
                };
                [results addObject:sampleDict];
            }
            
            resolve(results);
        }];
        
        [self.healthStore executeQuery:dayQuery];
    }];
    
    [self.healthStore executeQuery:query];
}

RCT_EXPORT_METHOD(getQuantitySamplesForRange:(NSString *)identifier
                  unit:(NSString *)unit
                  startDate:(NSString *)startDateString
                  endDate:(NSString *)endDateString
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    HKQuantityType *quantityType = [HKQuantityType quantityTypeForIdentifier:identifier];
    if (!quantityType) {
        reject(@"ERR_INVALID_TYPE", @"Invalid quantity type", nil);
        return;
    }
    
    HKUnit *hkUnit = [self unitFromString:unit];
    if (!hkUnit) {
        reject(@"ERR_INVALID_UNIT", @"Invalid unit", nil);
        return;
    }
    
    NSDate *startDate = [self dateFromISO8601String:startDateString];
    NSDate *endDate = [self dateFromISO8601String:endDateString];
    
    if (!startDate || !endDate) {
        reject(@"ERR_INVALID_DATE", @"Invalid date format", nil);
        return;
    }
    
    NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionStrictStartDate];
    
    HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:quantityType
                                                           predicate:predicate
                                                               limit:HKObjectQueryNoLimit
                                                     sortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:YES]]
                                                      resultsHandler:^(HKSampleQuery *query, NSArray *samples, NSError *error) {
        if (error) {
            reject(@"ERR_QUERY", @"Error querying data", error);
            return;
        }
        
        NSMutableArray *results = [[NSMutableArray alloc] init];
        for (HKQuantitySample *sample in samples) {
            double value = [sample.quantity doubleValueForUnit:hkUnit];
            NSDictionary *sampleDict = @{
                @"value": @(value),
                @"startDate": [self dateToISO8601String:sample.startDate],
                @"endDate": [self dateToISO8601String:sample.endDate],
                @"uuid": sample.UUID.UUIDString,
                @"sourceRevision": [self sourceRevisionToDict:sample.sourceRevision]
            };
            [results addObject:sampleDict];
        }
        
        resolve(results);
    }];
    
    [self.healthStore executeQuery:query];
}

RCT_EXPORT_METHOD(getLatestQuantitySample:(NSString *)identifier
                  unit:(NSString *)unit
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    HKQuantityType *quantityType = [HKQuantityType quantityTypeForIdentifier:identifier];
    if (!quantityType) {
        reject(@"ERR_INVALID_TYPE", @"Invalid quantity type", nil);
        return;
    }
    
    HKUnit *hkUnit = [self unitFromString:unit];
    if (!hkUnit) {
        reject(@"ERR_INVALID_UNIT", @"Invalid unit", nil);
        return;
    }
    
    HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:quantityType
                                                           predicate:nil
                                                               limit:1
                                                     sortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO]]
                                                      resultsHandler:^(HKSampleQuery *query, NSArray *samples, NSError *error) {
        if (error) {
            reject(@"ERR_QUERY", @"Error querying data", error);
            return;
        }
        
        if (samples.count == 0) {
            resolve([NSNull null]);
            return;
        }
        
        HKQuantitySample *sample = samples.firstObject;
        double value = [sample.quantity doubleValueForUnit:hkUnit];
        NSDictionary *sampleDict = @{
            @"value": @(value),
            @"startDate": [self dateToISO8601String:sample.startDate],
            @"endDate": [self dateToISO8601String:sample.endDate],
            @"uuid": sample.UUID.UUIDString,
            @"sourceRevision": [self sourceRevisionToDict:sample.sourceRevision]
        };
        
        resolve(sampleDict);
    }];
    
    [self.healthStore executeQuery:query];
}

RCT_EXPORT_METHOD(getCategorySamplesForDays:(NSString *)identifier
                  days:(nonnull NSNumber *)days
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    HKCategoryType *categoryType = [HKCategoryType categoryTypeForIdentifier:identifier];
    if (!categoryType) {
        reject(@"ERR_INVALID_TYPE", @"Invalid category type", nil);
        return;
    }
    
    NSDate *endDate = [NSDate date];
    NSDate *startDate = [NSDate dateWithTimeInterval:-(days.intValue * 24 * 60 * 60) sinceDate:endDate];
    
    NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionStrictStartDate];
    
    HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:categoryType
                                                           predicate:predicate
                                                               limit:HKObjectQueryNoLimit
                                                     sortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:YES]]
                                                      resultsHandler:^(HKSampleQuery *query, NSArray *samples, NSError *error) {
        if (error) {
            reject(@"ERR_QUERY", @"Error querying data", error);
            return;
        }
        
        NSMutableArray *results = [[NSMutableArray alloc] init];
        for (HKCategorySample *sample in samples) {
            NSDictionary *sampleDict = @{
                @"value": @(sample.value),
                @"startDate": [self dateToISO8601String:sample.startDate],
                @"endDate": [self dateToISO8601String:sample.endDate],
                @"uuid": sample.UUID.UUIDString,
                @"sourceRevision": [self sourceRevisionToDict:sample.sourceRevision]
            };
            [results addObject:sampleDict];
        }
        
        resolve(results);
    }];
    
    [self.healthStore executeQuery:query];
}

// MARK: - Statistics and Aggregation

RCT_EXPORT_METHOD(getStatisticsForType:(NSString *)identifier
                  unit:(NSString *)unit
                  startDate:(NSString *)startDateString
                  endDate:(NSString *)endDateString
                  options:(NSArray *)options
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    HKQuantityType *quantityType = [HKQuantityType quantityTypeForIdentifier:identifier];
    if (!quantityType) {
        reject(@"ERR_INVALID_TYPE", @"Invalid quantity type", nil);
        return;
    }
    
    HKUnit *hkUnit = [self unitFromString:unit];
    if (!hkUnit) {
        reject(@"ERR_INVALID_UNIT", @"Invalid unit", nil);
        return;
    }
    
    NSDate *startDate = [self dateFromISO8601String:startDateString];
    NSDate *endDate = [self dateFromISO8601String:endDateString];
    
    if (!startDate || !endDate) {
        reject(@"ERR_INVALID_DATE", @"Invalid date format", nil);
        return;
    }
    
    HKStatisticsOptions statisticsOptions = [self statisticsOptionsFromArray:options];
    
    HKStatisticsQuery *query = [[HKStatisticsQuery alloc] initWithQuantityType:quantityType
                                                        quantitySamplePredicate:nil
                                                                        options:statisticsOptions
                                                              completionHandler:^(HKStatisticsQuery *query, HKStatistics *statistics, NSError *error) {
        if (error) {
            reject(@"ERR_QUERY", @"Error querying statistics", error);
            return;
        }
        
        NSMutableDictionary *result = [[NSMutableDictionary alloc] init];
        
        if (statistics.sumQuantity) {
            result[@"sum"] = @([statistics.sumQuantity doubleValueForUnit:hkUnit]);
        }
        
        if (statistics.averageQuantity) {
            result[@"average"] = @([statistics.averageQuantity doubleValueForUnit:hkUnit]);
        }
        
        if (statistics.minimumQuantity) {
            result[@"minimum"] = @([statistics.minimumQuantity doubleValueForUnit:hkUnit]);
        }
        
        if (statistics.maximumQuantity) {
            result[@"maximum"] = @([statistics.maximumQuantity doubleValueForUnit:hkUnit]);
        }
        
        if (statistics.mostRecentQuantity) {
            result[@"mostRecent"] = @([statistics.mostRecentQuantity doubleValueForUnit:hkUnit]);
        }
        
        result[@"startDate"] = [self dateToISO8601String:statistics.startDate];
        result[@"endDate"] = [self dateToISO8601String:statistics.endDate];
        
        resolve(result);
    }];
    
    [self.healthStore executeQuery:query];
}

// MARK: - Workouts

RCT_EXPORT_METHOD(getWorkouts:(NSString *)startDateString
                  endDate:(NSString *)endDateString
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    NSDate *startDate = [self dateFromISO8601String:startDateString];
    NSDate *endDate = [self dateFromISO8601String:endDateString];
    
    if (!startDate || !endDate) {
        reject(@"ERR_INVALID_DATE", @"Invalid date format", nil);
        return;
    }
    
    NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionStrictStartDate];
    
    HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:[HKObjectType workoutType]
                                                           predicate:predicate
                                                               limit:HKObjectQueryNoLimit
                                                     sortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO]]
                                                      resultsHandler:^(HKSampleQuery *query, NSArray *samples, NSError *error) {
        if (error) {
            reject(@"ERR_QUERY", @"Error querying workouts", error);
            return;
        }
        
        NSMutableArray *results = [[NSMutableArray alloc] init];
        for (HKWorkout *workout in samples) {
            NSDictionary *workoutDict = [self workoutToDict:workout];
            [results addObject:workoutDict];
        }
        
        resolve(results);
    }];
    
    [self.healthStore executeQuery:query];
}

RCT_EXPORT_METHOD(getWorkoutsForDays:(nonnull NSNumber *)days
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    NSDate *endDate = [NSDate date];
    NSDate *startDate = [NSDate dateWithTimeInterval:-(days.intValue * 24 * 60 * 60) sinceDate:endDate];
    
    NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionStrictStartDate];
    
    HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:[HKObjectType workoutType]
                                                           predicate:predicate
                                                               limit:HKObjectQueryNoLimit
                                                     sortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO]]
                                                      resultsHandler:^(HKSampleQuery *query, NSArray *samples, NSError *error) {
        if (error) {
            reject(@"ERR_QUERY", @"Error querying workouts", error);
            return;
        }
        
        NSMutableArray *results = [[NSMutableArray alloc] init];
        for (HKWorkout *workout in samples) {
            NSDictionary *workoutDict = [self workoutToDict:workout];
            [results addObject:workoutDict];
        }
        
        resolve(results);
    }];
    
    [self.healthStore executeQuery:query];
}

// MARK: - Data Writing

RCT_EXPORT_METHOD(saveQuantitySample:(NSString *)identifier
                  value:(NSNumber *)value
                  unit:(NSString *)unit
                  startDate:(NSString *)startDateString
                  endDate:(NSString *)endDateString
                  metadata:(NSDictionary *)metadata
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    HKQuantityType *quantityType = [HKQuantityType quantityTypeForIdentifier:identifier];
    if (!quantityType) {
        reject(@"ERR_INVALID_TYPE", @"Invalid quantity type", nil);
        return;
    }
    
    HKUnit *hkUnit = [self unitFromString:unit];
    if (!hkUnit) {
        reject(@"ERR_INVALID_UNIT", @"Invalid unit", nil);
        return;
    }
    
    NSDate *startDate = [self dateFromISO8601String:startDateString];
    NSDate *endDate = [self dateFromISO8601String:endDateString];
    
    if (!startDate || !endDate) {
        reject(@"ERR_INVALID_DATE", @"Invalid date format", nil);
        return;
    }
    
    HKQuantity *quantity = [HKQuantity quantityWithUnit:hkUnit doubleValue:value.doubleValue];
    HKQuantitySample *sample = [HKQuantitySample quantitySampleWithType:quantityType
                                                               quantity:quantity
                                                              startDate:startDate
                                                                endDate:endDate
                                                               metadata:metadata];
    
    [self.healthStore saveObject:sample withCompletion:^(BOOL success, NSError *error) {
        if (success) {
            resolve(@(YES));
        } else {
            reject(@"ERR_SAVE", @"Error saving sample", error);
        }
    }];
}

RCT_EXPORT_METHOD(saveCategorySample:(NSString *)identifier
                  value:(NSNumber *)value
                  startDate:(NSString *)startDateString
                  endDate:(NSString *)endDateString
                  metadata:(NSDictionary *)metadata
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    HKCategoryType *categoryType = [HKCategoryType categoryTypeForIdentifier:identifier];
    if (!categoryType) {
        reject(@"ERR_INVALID_TYPE", @"Invalid category type", nil);
        return;
    }
    
    NSDate *startDate = [self dateFromISO8601String:startDateString];
    NSDate *endDate = [self dateFromISO8601String:endDateString];
    
    if (!startDate || !endDate) {
        reject(@"ERR_INVALID_DATE", @"Invalid date format", nil);
        return;
    }
    
    HKCategorySample *sample = [HKCategorySample categorySampleWithType:categoryType
                                                                   value:value.integerValue
                                                               startDate:startDate
                                                                 endDate:endDate
                                                                metadata:metadata];
    
    [self.healthStore saveObject:sample withCompletion:^(BOOL success, NSError *error) {
        if (success) {
            resolve(@(YES));
        } else {
            reject(@"ERR_SAVE", @"Error saving sample", error);
        }
    }];
}

// MARK: - Background Observers

RCT_EXPORT_METHOD(startBackgroundObserver:(NSString *)identifier
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    HKSampleType *sampleType = [self getHKSampleTypeFromString:identifier];
    if (!sampleType) {
        reject(@"ERR_INVALID_TYPE", @"Invalid type", nil);
        return;
    }
    
    if (self.observers[identifier]) {
        resolve(@"Observer already active");
        return;
    }
    
    HKObserverQuery *observerQuery = [[HKObserverQuery alloc] initWithSampleType:sampleType
                                                                       predicate:nil
                                                                   updateHandler:^(HKObserverQuery *query, HKObserverQueryCompletionHandler completionHandler, NSError *error) {
        if (error) {
            RCTLogError(@"Observer error: %@", error);
        } else if (self.hasListeners) {
            [self sendEventWithName:@"healthKitDataChanged" body:@{@"identifier": identifier}];
        }
        
        completionHandler();
    }];
    
    [self.healthStore executeQuery:observerQuery];
    self.observers[identifier] = observerQuery;
    
    resolve(@"Observer started");
}

RCT_EXPORT_METHOD(stopBackgroundObserver:(NSString *)identifier
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    HKObserverQuery *observerQuery = self.observers[identifier];
    if (observerQuery) {
        [self.healthStore stopQuery:observerQuery];
        [self.observers removeObjectForKey:identifier];
        resolve(@"Observer stopped");
    } else {
        reject(@"ERR_NO_OBSERVER", @"Observer not found", nil);
    }
}

// MARK: - Utility Methods

RCT_EXPORT_METHOD(getAvailableTypes:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    NSArray *types = [self getAllHealthKitTypes];
    resolve(types);
}

RCT_EXPORT_METHOD(getSupportedUnits:(NSString *)identifier
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    HKQuantityType *quantityType = [HKQuantityType quantityTypeForIdentifier:identifier];
    if (!quantityType) {
        reject(@"ERR_INVALID_TYPE", @"Invalid quantity type", nil);
        return;
    }
    
    NSArray *units = [self getSupportedUnitsForType:quantityType];
    resolve(units);
}

// MARK: - Enhanced Authorization Methods

RCT_EXPORT_METHOD(isTypeAvailable:(NSArray *)identifiers
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    if (![HKHealthStore isHealthDataAvailable]) {
        resolve(@{});
        return;
    }
    
    if (!identifiers || ![identifiers isKindOfClass:[NSArray class]] || identifiers.count == 0) {
        reject(@"ERR_INVALID_INPUT", @"Invalid or empty identifiers array", nil);
        return;
    }
    
    NSMutableDictionary *results = [[NSMutableDictionary alloc] init];
    NSMutableArray *failedIdentifiers = [[NSMutableArray alloc] init];
    
    for (NSString *identifier in identifiers) {
        if (![identifier isKindOfClass:[NSString class]] || identifier.length == 0) {
            [failedIdentifiers addObject:identifier ?: @"null"];
            continue;
        }
        
        @try {
            HKObjectType *type = [self getHKObjectTypeFromString:identifier];
            BOOL isAvailable = (type != nil);
            results[identifier] = @(isAvailable);
        } @catch (NSException *exception) {
            results[identifier] = @(NO);
            [failedIdentifiers addObject:identifier];
        }
    }
    
    if (failedIdentifiers.count > 0) {
        NSLog(@"Failed to check availability for: %@", [failedIdentifiers componentsJoinedByString:@", "]);
    }
    
    resolve(results);
}

RCT_EXPORT_METHOD(canReadType:(NSArray *)identifiers
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    if (![HKHealthStore isHealthDataAvailable]) {
        resolve(@{});
        return;
    }
    
    if (!identifiers || ![identifiers isKindOfClass:[NSArray class]] || identifiers.count == 0) {
        reject(@"ERR_INVALID_INPUT", @"Invalid or empty identifiers array", nil);
        return;
    }
    
    NSMutableDictionary *results = [[NSMutableDictionary alloc] init];
    NSMutableArray *failedIdentifiers = [[NSMutableArray alloc] init];
    
    for (NSString *identifier in identifiers) {
        if (![identifier isKindOfClass:[NSString class]] || identifier.length == 0) {
            [failedIdentifiers addObject:identifier ?: @"null"];
            continue;
        }
        
        @try {
            HKObjectType *type = [self getHKObjectTypeFromString:identifier];
            if (!type) {
                results[identifier] = @(NO);
                continue;
            }
            
            HKAuthorizationStatus status = [self.healthStore authorizationStatusForType:type];
            BOOL canRead = (status == HKAuthorizationStatusSharingAuthorized);
            results[identifier] = @(canRead);
        } @catch (NSException *exception) {
            results[identifier] = @(NO);
            [failedIdentifiers addObject:identifier];
        }
    }
    
    if (failedIdentifiers.count > 0) {
        NSLog(@"Failed to check read permission for: %@", [failedIdentifiers componentsJoinedByString:@", "]);
    }
    
    resolve(results);
}

RCT_EXPORT_METHOD(canWriteType:(NSArray *)identifiers
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    if (![HKHealthStore isHealthDataAvailable]) {
        resolve(@{});
        return;
    }
    
    if (!identifiers || ![identifiers isKindOfClass:[NSArray class]] || identifiers.count == 0) {
        reject(@"ERR_INVALID_INPUT", @"Invalid or empty identifiers array", nil);
        return;
    }
    
    NSMutableDictionary *results = [[NSMutableDictionary alloc] init];
    NSMutableArray *failedIdentifiers = [[NSMutableArray alloc] init];
    
    for (NSString *identifier in identifiers) {
        if (![identifier isKindOfClass:[NSString class]] || identifier.length == 0) {
            [failedIdentifiers addObject:identifier ?: @"null"];
            continue;
        }
        
        @try {
            HKSampleType *type = [self getHKSampleTypeFromString:identifier];
            if (!type) {
                results[identifier] = @(NO);
                continue;
            }
            
            HKAuthorizationStatus status = [self.healthStore authorizationStatusForType:type];
            BOOL canWrite = (status == HKAuthorizationStatusSharingAuthorized);
            results[identifier] = @(canWrite);
        } @catch (NSException *exception) {
            results[identifier] = @(NO);
            [failedIdentifiers addObject:identifier];
        }
    }
    
    if (failedIdentifiers.count > 0) {
        NSLog(@"Failed to check write permission for: %@", [failedIdentifiers componentsJoinedByString:@", "]);
    }
    
    resolve(results);
}

RCT_EXPORT_METHOD(requestReadAuthorization:(NSArray *)readTypes
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    if (![HKHealthStore isHealthDataAvailable]) {
        reject(@"ERR_HEALTHKIT_UNAVAILABLE", @"HealthKit is not available on this device", nil);
        return;
    }
    
    if (!readTypes || ![readTypes isKindOfClass:[NSArray class]] || readTypes.count == 0) {
        reject(@"ERR_INVALID_INPUT", @"Invalid or empty readTypes array", nil);
        return;
    }
    
    NSMutableSet *typesToRead = [[NSMutableSet alloc] init];
    NSMutableArray *failedTypes = [[NSMutableArray alloc] init];
    
    for (NSString *identifier in readTypes) {
        if (![identifier isKindOfClass:[NSString class]] || identifier.length == 0) {
            [failedTypes addObject:identifier ?: @"null"];
            continue;
        }
        
        @try {
            HKObjectType *type = [self getHKObjectTypeFromString:identifier];
            if (type) {
                [typesToRead addObject:type];
            } else {
                [failedTypes addObject:identifier];
            }
        } @catch (NSException *exception) {
            [failedTypes addObject:identifier];
        }
    }
    
    if (failedTypes.count > 0) {
        NSLog(@"Failed to process read types: %@", [failedTypes componentsJoinedByString:@", "]);
    }
    
    if (typesToRead.count == 0) {
        resolve(@(YES));
        return;
    }
    
    // Request read-only authorization
    if ([NSThread isMainThread]) {
        @try {
            [self.healthStore requestAuthorizationToShareTypes:[NSSet set]
                                                     readTypes:typesToRead
                                                    completion:^(BOOL success, NSError *error) {
                if (success) {
                    resolve(@(YES));
                } else {
                    NSString *errorMessage = error ? error.localizedDescription : @"Failed to request read authorization";
                    reject(@"ERR_AUTHORIZATION", errorMessage, error);
                }
            }];
        } @catch (NSException *exception) {
            NSLog(@"Exception in requestReadAuthorization: %@", exception.reason);
            reject(@"ERR_AUTHORIZATION", @"Property is not configurable", nil);
        }
    } else {
        dispatch_async(dispatch_get_main_queue(), ^{
            @try {
                [self.healthStore requestAuthorizationToShareTypes:[NSSet set]
                                                         readTypes:typesToRead
                                                        completion:^(BOOL success, NSError *error) {
                    if (success) {
                        resolve(@(YES));
                    } else {
                        NSString *errorMessage = error ? error.localizedDescription : @"Failed to request read authorization";
                        reject(@"ERR_AUTHORIZATION", errorMessage, error);
                    }
                }];
            } @catch (NSException *exception) {
                NSLog(@"Exception in requestReadAuthorization: %@", exception.reason);
                reject(@"ERR_AUTHORIZATION", @"Property is not configurable", nil);
            }
        });
    }
}

RCT_EXPORT_METHOD(requestWriteAuthorization:(NSArray *)writeTypes
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    if (![HKHealthStore isHealthDataAvailable]) {
        reject(@"ERR_HEALTHKIT_UNAVAILABLE", @"HealthKit is not available on this device", nil);
        return;
    }
    
    if (!writeTypes || ![writeTypes isKindOfClass:[NSArray class]] || writeTypes.count == 0) {
        reject(@"ERR_INVALID_INPUT", @"Invalid or empty writeTypes array", nil);
        return;
    }
    
    NSMutableSet *typesToWrite = [[NSMutableSet alloc] init];
    NSMutableArray *failedTypes = [[NSMutableArray alloc] init];
    
    for (NSString *identifier in writeTypes) {
        if (![identifier isKindOfClass:[NSString class]] || identifier.length == 0) {
            [failedTypes addObject:identifier ?: @"null"];
            continue;
        }
        
        @try {
            HKSampleType *type = [self getHKSampleTypeFromString:identifier];
            if (type) {
                [typesToWrite addObject:type];
            } else {
                [failedTypes addObject:identifier];
            }
        } @catch (NSException *exception) {
            [failedTypes addObject:identifier];
        }
    }
    
    if (failedTypes.count > 0) {
        NSLog(@"Failed to process write types: %@", [failedTypes componentsJoinedByString:@", "]);
    }
    
    if (typesToWrite.count == 0) {
        resolve(@(YES));
        return;
    }
    
    // Request write authorization (also needs read for some types)
    if ([NSThread isMainThread]) {
        @try {
            [self.healthStore requestAuthorizationToShareTypes:typesToWrite
                                                     readTypes:[NSSet set]
                                                    completion:^(BOOL success, NSError *error) {
                if (success) {
                    resolve(@(YES));
                } else {
                    NSString *errorMessage = error ? error.localizedDescription : @"Failed to request write authorization";
                    reject(@"ERR_AUTHORIZATION", errorMessage, error);
                }
            }];
        } @catch (NSException *exception) {
            NSLog(@"Exception in requestWriteAuthorization: %@", exception.reason);
            reject(@"ERR_AUTHORIZATION", @"Property is not configurable", nil);
        }
    } else {
        dispatch_async(dispatch_get_main_queue(), ^{
            @try {
                [self.healthStore requestAuthorizationToShareTypes:typesToWrite
                                                         readTypes:[NSSet set]
                                                        completion:^(BOOL success, NSError *error) {
                    if (success) {
                        resolve(@(YES));
                    } else {
                        NSString *errorMessage = error ? error.localizedDescription : @"Failed to request write authorization";
                        reject(@"ERR_AUTHORIZATION", errorMessage, error);
                    }
                }];
            } @catch (NSException *exception) {
                NSLog(@"Exception in requestWriteAuthorization: %@", exception.reason);
                reject(@"ERR_AUTHORIZATION", @"Property is not configurable", nil);
            }
        });
    }
}

RCT_EXPORT_METHOD(getDetailedAuthorizationStatus:(NSArray *)identifiers
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    if (![HKHealthStore isHealthDataAvailable]) {
        reject(@"ERR_HEALTHKIT_UNAVAILABLE", @"HealthKit is not available on this device", nil);
        return;
    }
    
    if (!identifiers || ![identifiers isKindOfClass:[NSArray class]] || identifiers.count == 0) {
        reject(@"ERR_INVALID_INPUT", @"Invalid or empty identifiers array", nil);
        return;
    }
    
    NSMutableArray *results = [[NSMutableArray alloc] init];
    NSMutableArray *failedIdentifiers = [[NSMutableArray alloc] init];
    
    for (NSString *identifier in identifiers) {
        if (![identifier isKindOfClass:[NSString class]] || identifier.length == 0) {
            [failedIdentifiers addObject:identifier ?: @"null"];
            continue;
        }
        
        @try {
            HKObjectType *type = [self getHKObjectTypeFromString:identifier];
            if (!type) {
                NSDictionary *result = @{
                    @"identifier": identifier,
                    @"status": @"unknown",
                    @"canRead": @(NO),
                    @"canWrite": @(NO),
                    @"isAvailable": @(NO)
                };
                [results addObject:result];
                continue;
            }
            
            HKAuthorizationStatus status = [self.healthStore authorizationStatusForType:type];
            NSString *statusString = [self authorizationStatusToString:status];
            
            NSDictionary *result = @{
                @"identifier": identifier,
                @"status": statusString,
                @"canRead": @(status == HKAuthorizationStatusSharingAuthorized),
                @"canWrite": @(status == HKAuthorizationStatusSharingAuthorized),
                @"isAvailable": @(YES)
            };
            
            [results addObject:result];
        } @catch (NSException *exception) {
            NSDictionary *result = @{
                @"identifier": identifier,
                @"status": @"error",
                @"canRead": @(NO),
                @"canWrite": @(NO),
                @"isAvailable": @(NO)
            };
            [results addObject:result];
            [failedIdentifiers addObject:identifier];
        }
    }
    
    if (failedIdentifiers.count > 0) {
        NSLog(@"Failed to get detailed status for: %@", [failedIdentifiers componentsJoinedByString:@", "]);
    }
    
    resolve(results);
}

// MARK: - Helper Methods

- (void)stopAllObservers {
    if (!self.observers || self.observers.count == 0) {
        return;
    }
    
    for (NSString *key in self.observers.allKeys) {
        HKObserverQuery *query = self.observers[key];
        if (query) {
            [self.healthStore stopQuery:query];
        }
    }
    [self.observers removeAllObjects];
}

- (void)dealloc {
    [self stopAllObservers];
}

- (NSSet *)getAllReadTypes {
    return [NSSet setWithObjects:
        // Quantity Types
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierActiveEnergyBurned],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierFlightsClimbed],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierRestingHeartRate],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierWalkingHeartRateAverage],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRateVariabilitySDNN],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierVO2Max],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyFatPercentage],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierLeanBodyMass],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBasalEnergyBurned],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceCycling],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceSwimming],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierSwimmingStrokeCount],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyTemperature],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodPressureSystolic],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodPressureDiastolic],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodGlucose],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierOxygenSaturation],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierRespiratoryRate],
        
        // Category Types
        [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierSleepAnalysis],
        [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierMindfulSession],
        [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierAppleStandHour],
        [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierCervicalMucusQuality],
        [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierMenstrualFlow],
        [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierIntermenstrualBleeding],
        [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierSexualActivity],
        
        // Workouts
        [HKObjectType workoutType],
        
        // Characteristics
        [HKObjectType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBiologicalSex],
        [HKObjectType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierDateOfBirth],
        [HKObjectType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBloodType],
        [HKObjectType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierFitzpatrickSkinType],
        nil];
}

- (NSSet *)getAllWriteTypes {
    return [NSSet setWithObjects:
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierActiveEnergyBurned],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierFlightsClimbed],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyFatPercentage],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierLeanBodyMass],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBasalEnergyBurned],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceCycling],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceSwimming],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierSwimmingStrokeCount],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyTemperature],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodPressureSystolic],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodPressureDiastolic],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodGlucose],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierOxygenSaturation],
        [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierRespiratoryRate],
        [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierSleepAnalysis],
        [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierMindfulSession],
        [HKObjectType workoutType],
        nil];
}

- (HKObjectType *)getHKObjectTypeFromString:(NSString *)identifier {
    if (!identifier || ![identifier isKindOfClass:[NSString class]] || identifier.length == 0) {
        NSLog(@"❌ [Native] getHKObjectTypeFromString: identifier inválido");
        return nil;
    }
    
    NSLog(@"🔍 [Native] getHKObjectTypeFromString: processando %@", identifier);
    
    @try {
        // Try quantity type first
        NSLog(@"🔍 [Native] Tentando quantity type...");
        HKObjectType *type = [HKQuantityType quantityTypeForIdentifier:identifier];
        if (type) {
            NSLog(@"✅ [Native] Quantity type encontrado: %@", type.identifier);
            return type;
        }
        
        // Try category type
        NSLog(@"🔍 [Native] Tentando category type...");
        type = [HKCategoryType categoryTypeForIdentifier:identifier];
        if (type) {
            NSLog(@"✅ [Native] Category type encontrado: %@", type.identifier);
            return type;
        }
        
        // Try characteristic type
        NSLog(@"🔍 [Native] Tentando characteristic type...");
        type = [HKCharacteristicType characteristicTypeForIdentifier:identifier];
        if (type) {
            NSLog(@"✅ [Native] Characteristic type encontrado: %@", type.identifier);
            return type;
        }
        
        if ([identifier isEqualToString:@"HKWorkoutTypeIdentifier"]) {
            NSLog(@"✅ [Native] Workout type encontrado");
            return [HKWorkoutType workoutType];
        }
        
        NSLog(@"❌ [Native] Tipo não encontrado para: %@", identifier);
    } @catch (NSException *exception) {
        NSLog(@"❌ [Native] Exception getting type for identifier %@: %@", identifier, exception.reason);
        NSLog(@"❌ [Native] Exception name: %@", exception.name);
        NSLog(@"❌ [Native] Exception userInfo: %@", exception.userInfo);
        return nil;
    }
    
    return nil;
}

- (HKSampleType *)getHKSampleTypeFromString:(NSString *)identifier {
    HKSampleType *type = [HKSampleType quantityTypeForIdentifier:identifier];
    if (!type) {
        type = [HKSampleType categoryTypeForIdentifier:identifier];
    }
    if (!type && [identifier isEqualToString:@"HKWorkoutTypeIdentifier"]) {
        type = [HKSampleType workoutType];
    }
    return type;
}

- (NSString *)authorizationStatusToString:(HKAuthorizationStatus)status {
    switch (status) {
        case HKAuthorizationStatusNotDetermined:
            return @"notDetermined";
        case HKAuthorizationStatusSharingDenied:
            return @"sharingDenied";
        case HKAuthorizationStatusSharingAuthorized:
            return @"sharingAuthorized";
        default:
            return @"unknown";
    }
}

- (HKUnit *)unitFromString:(NSString *)unitString {
    if ([unitString isEqualToString:@"count"]) {
        return [HKUnit countUnit];
    } else if ([unitString isEqualToString:@"km"]) {
        return [HKUnit meterUnitWithMetricPrefix:HKMetricPrefixKilo];
    } else if ([unitString isEqualToString:@"m"]) {
        return [HKUnit meterUnit];
    } else if ([unitString isEqualToString:@"kcal"]) {
        return [HKUnit kilocalorieUnit];
    } else if ([unitString isEqualToString:@"cal"]) {
        return [HKUnit largeCalorieUnit];
    } else if ([unitString isEqualToString:@"min"]) {
        return [HKUnit minuteUnit];
    } else if ([unitString isEqualToString:@"hr"]) {
        return [HKUnit hourUnit];
    } else if ([unitString isEqualToString:@"s"]) {
        return [HKUnit secondUnit];
    } else if ([unitString isEqualToString:@"bpm"]) {
        return [[HKUnit countUnit] unitDividedByUnit:[HKUnit minuteUnit]];
    } else if ([unitString isEqualToString:@"kg"]) {
        return [HKUnit gramUnitWithMetricPrefix:HKMetricPrefixKilo];
    } else if ([unitString isEqualToString:@"g"]) {
        return [HKUnit gramUnit];
    } else if ([unitString isEqualToString:@"lb"]) {
        return [HKUnit poundUnit];
    } else if ([unitString isEqualToString:@"cm"]) {
        return [HKUnit meterUnitWithMetricPrefix:HKMetricPrefixCenti];
    } else if ([unitString isEqualToString:@"mm"]) {
        return [HKUnit meterUnitWithMetricPrefix:HKMetricPrefixMilli];
    } else if ([unitString isEqualToString:@"ft"]) {
        return [HKUnit footUnit];
    } else if ([unitString isEqualToString:@"in"]) {
        return [HKUnit inchUnit];
    } else if ([unitString isEqualToString:@"°C"]) {
        return [HKUnit degreeCelsiusUnit];
    } else if ([unitString isEqualToString:@"°F"]) {
        return [HKUnit degreeFahrenheitUnit];
    } else if ([unitString isEqualToString:@"mmHg"]) {
        return [HKUnit millimeterOfMercuryUnit];
    } else if ([unitString isEqualToString:@"mg/dL"]) {
        return [HKUnit unitFromString:@"mg/dL"];
    } else if ([unitString isEqualToString:@"mmol/L"]) {
        return [HKUnit unitFromString:@"mmol/L"];
    } else if ([unitString isEqualToString:@"%"]) {
        return [HKUnit percentUnit];
    } else if ([unitString isEqualToString:@"breaths/min"]) {
        return [[HKUnit countUnit] unitDividedByUnit:[HKUnit minuteUnit]];
    }
    return nil;
}

- (NSString *)dateToISO8601String:(NSDate *)date {
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
    [formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
    return [formatter stringFromDate:date];
}

- (NSDate *)dateFromISO8601String:(NSString *)dateString {
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
    [formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
    return [formatter dateFromString:dateString];
}

- (NSDictionary *)sourceRevisionToDict:(HKSourceRevision *)sourceRevision {
    return @{
        @"source": @{
            @"name": sourceRevision.source.name ?: @"",
            @"bundleIdentifier": sourceRevision.source.bundleIdentifier ?: @""
        },
        @"version": sourceRevision.version ?: @"",
        @"productType": sourceRevision.productType ?: @"",
        @"systemVersion": @""
    };
}

- (NSDictionary *)workoutToDict:(HKWorkout *)workout {
    NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
    
    dict[@"uuid"] = workout.UUID.UUIDString;
    dict[@"startDate"] = [self dateToISO8601String:workout.startDate];
    dict[@"endDate"] = [self dateToISO8601String:workout.endDate];
    dict[@"workoutActivityType"] = @(workout.workoutActivityType);
    dict[@"duration"] = @(workout.duration);
    dict[@"sourceRevision"] = [self sourceRevisionToDict:workout.sourceRevision];
    
    if (workout.totalEnergyBurned) {
        dict[@"totalEnergyBurned"] = @([workout.totalEnergyBurned doubleValueForUnit:[HKUnit kilocalorieUnit]]);
    }
    
    if (workout.totalDistance) {
        dict[@"totalDistance"] = @([workout.totalDistance doubleValueForUnit:[HKUnit meterUnit]]);
    }
    
    if (workout.totalSwimmingStrokeCount) {
        dict[@"totalSwimmingStrokeCount"] = @([workout.totalSwimmingStrokeCount doubleValueForUnit:[HKUnit countUnit]]);
    }
    
    if (workout.totalFlightsClimbed) {
        dict[@"totalFlightsClimbed"] = @([workout.totalFlightsClimbed doubleValueForUnit:[HKUnit countUnit]]);
    }
    
    if (workout.metadata) {
        dict[@"metadata"] = workout.metadata;
    }
    
    return dict;
}

- (HKStatisticsOptions)statisticsOptionsFromArray:(NSArray *)options {
    HKStatisticsOptions statisticsOptions = 0;
    
    for (NSString *option in options) {
        if ([option isEqualToString:@"sum"]) {
            statisticsOptions |= HKStatisticsOptionCumulativeSum;
        } else if ([option isEqualToString:@"average"]) {
            statisticsOptions |= HKStatisticsOptionDiscreteAverage;
        } else if ([option isEqualToString:@"min"]) {
            statisticsOptions |= HKStatisticsOptionDiscreteMin;
        } else if ([option isEqualToString:@"max"]) {
            statisticsOptions |= HKStatisticsOptionDiscreteMax;
        } else if ([option isEqualToString:@"mostRecent"]) {
            statisticsOptions |= HKStatisticsOptionMostRecent;
        }
    }
    
    return statisticsOptions;
}

- (NSArray *)getAllHealthKitTypes {
    return @[
        // Activity & Fitness
        @{@"identifier": HKQuantityTypeIdentifierStepCount, @"name": @"Steps", @"category": @"activity", @"type": @"quantity", @"unit": @"count"},
        @{@"identifier": HKQuantityTypeIdentifierDistanceWalkingRunning, @"name": @"Distance Walking/Running", @"category": @"activity", @"type": @"quantity", @"unit": @"m"},
        @{@"identifier": HKQuantityTypeIdentifierDistanceCycling, @"name": @"Distance Cycling", @"category": @"activity", @"type": @"quantity", @"unit": @"m"},
        @{@"identifier": HKQuantityTypeIdentifierDistanceSwimming, @"name": @"Distance Swimming", @"category": @"activity", @"type": @"quantity", @"unit": @"m"},
        @{@"identifier": HKQuantityTypeIdentifierActiveEnergyBurned, @"name": @"Active Energy Burned", @"category": @"activity", @"type": @"quantity", @"unit": @"kcal"},
        @{@"identifier": HKQuantityTypeIdentifierBasalEnergyBurned, @"name": @"Basal Energy Burned", @"category": @"activity", @"type": @"quantity", @"unit": @"kcal"},
        @{@"identifier": HKQuantityTypeIdentifierAppleExerciseTime, @"name": @"Apple Exercise Time", @"category": @"activity", @"type": @"quantity", @"unit": @"min"},
        @{@"identifier": HKQuantityTypeIdentifierFlightsClimbed, @"name": @"Flights Climbed", @"category": @"activity", @"type": @"quantity", @"unit": @"count"},
        @{@"identifier": HKQuantityTypeIdentifierSwimmingStrokeCount, @"name": @"Swimming Stroke Count", @"category": @"activity", @"type": @"quantity", @"unit": @"count"},
        
        // Heart
        @{@"identifier": HKQuantityTypeIdentifierHeartRate, @"name": @"Heart Rate", @"category": @"heart", @"type": @"quantity", @"unit": @"bpm"},
        @{@"identifier": HKQuantityTypeIdentifierRestingHeartRate, @"name": @"Resting Heart Rate", @"category": @"heart", @"type": @"quantity", @"unit": @"bpm"},
        @{@"identifier": HKQuantityTypeIdentifierWalkingHeartRateAverage, @"name": @"Walking Heart Rate Average", @"category": @"heart", @"type": @"quantity", @"unit": @"bpm"},
        @{@"identifier": HKQuantityTypeIdentifierHeartRateVariabilitySDNN, @"name": @"Heart Rate Variability", @"category": @"heart", @"type": @"quantity", @"unit": @"ms"},
        
        // Body Measurements
        @{@"identifier": HKQuantityTypeIdentifierHeight, @"name": @"Height", @"category": @"body", @"type": @"quantity", @"unit": @"cm"},
        @{@"identifier": HKQuantityTypeIdentifierBodyMass, @"name": @"Weight", @"category": @"body", @"type": @"quantity", @"unit": @"kg"},
        @{@"identifier": HKQuantityTypeIdentifierBodyFatPercentage, @"name": @"Body Fat Percentage", @"category": @"body", @"type": @"quantity", @"unit": @"%"},
        @{@"identifier": HKQuantityTypeIdentifierLeanBodyMass, @"name": @"Lean Body Mass", @"category": @"body", @"type": @"quantity", @"unit": @"kg"},
        @{@"identifier": HKQuantityTypeIdentifierBodyTemperature, @"name": @"Body Temperature", @"category": @"body", @"type": @"quantity", @"unit": @"°C"},
        
        // Vitals
        @{@"identifier": HKQuantityTypeIdentifierBloodPressureSystolic, @"name": @"Blood Pressure Systolic", @"category": @"vitals", @"type": @"quantity", @"unit": @"mmHg"},
        @{@"identifier": HKQuantityTypeIdentifierBloodPressureDiastolic, @"name": @"Blood Pressure Diastolic", @"category": @"vitals", @"type": @"quantity", @"unit": @"mmHg"},
        @{@"identifier": HKQuantityTypeIdentifierOxygenSaturation, @"name": @"Oxygen Saturation", @"category": @"vitals", @"type": @"quantity", @"unit": @"%"},
        @{@"identifier": HKQuantityTypeIdentifierRespiratoryRate, @"name": @"Respiratory Rate", @"category": @"vitals", @"type": @"quantity", @"unit": @"breaths/min"},
        
        // Lab Results
        @{@"identifier": HKQuantityTypeIdentifierBloodGlucose, @"name": @"Blood Glucose", @"category": @"lab", @"type": @"quantity", @"unit": @"mg/dL"},
        @{@"identifier": HKQuantityTypeIdentifierVO2Max, @"name": @"VO2 Max", @"category": @"lab", @"type": @"quantity", @"unit": @"mL/kg·min"},
        
        // Sleep
        @{@"identifier": HKCategoryTypeIdentifierSleepAnalysis, @"name": @"Sleep Analysis", @"category": @"sleep", @"type": @"category"},
        
        // Mindfulness
        @{@"identifier": HKCategoryTypeIdentifierMindfulSession, @"name": @"Mindful Session", @"category": @"mindfulness", @"type": @"category"},
        
        // Activity Summary
        @{@"identifier": HKCategoryTypeIdentifierAppleStandHour, @"name": @"Apple Stand Hour", @"category": @"activity", @"type": @"category"},
        
        // Reproductive Health
        @{@"identifier": HKCategoryTypeIdentifierMenstrualFlow, @"name": @"Menstrual Flow", @"category": @"reproductive", @"type": @"category"},
        @{@"identifier": HKCategoryTypeIdentifierIntermenstrualBleeding, @"name": @"Intermenstrual Bleeding", @"category": @"reproductive", @"type": @"category"},
        @{@"identifier": HKCategoryTypeIdentifierSexualActivity, @"name": @"Sexual Activity", @"category": @"reproductive", @"type": @"category"},
        @{@"identifier": HKCategoryTypeIdentifierCervicalMucusQuality, @"name": @"Cervical Mucus Quality", @"category": @"reproductive", @"type": @"category"},
        
        // Workouts
        @{@"identifier": @"HKWorkoutTypeIdentifier", @"name": @"Workouts", @"category": @"workouts", @"type": @"workout"}
    ];
}

- (NSArray *)getSupportedUnitsForType:(HKQuantityType *)quantityType {
    NSString *identifier = quantityType.identifier;
    
    if ([identifier isEqualToString:HKQuantityTypeIdentifierStepCount] ||
        [identifier isEqualToString:HKQuantityTypeIdentifierFlightsClimbed] ||
        [identifier isEqualToString:HKQuantityTypeIdentifierSwimmingStrokeCount]) {
        return @[@"count"];
    } else if ([identifier isEqualToString:HKQuantityTypeIdentifierDistanceWalkingRunning] ||
               [identifier isEqualToString:HKQuantityTypeIdentifierDistanceCycling] ||
               [identifier isEqualToString:HKQuantityTypeIdentifierDistanceSwimming]) {
        return @[@"m", @"km", @"ft", @"mi"];
    } else if ([identifier isEqualToString:HKQuantityTypeIdentifierActiveEnergyBurned] ||
               [identifier isEqualToString:HKQuantityTypeIdentifierBasalEnergyBurned]) {
        return @[@"kcal", @"cal", @"kJ"];
    } else if ([identifier isEqualToString:HKQuantityTypeIdentifierAppleExerciseTime]) {
        return @[@"min", @"hr", @"s"];
    } else if ([identifier isEqualToString:HKQuantityTypeIdentifierHeartRate] ||
               [identifier isEqualToString:HKQuantityTypeIdentifierRestingHeartRate] ||
               [identifier isEqualToString:HKQuantityTypeIdentifierWalkingHeartRateAverage]) {
        return @[@"bpm"];
    } else if ([identifier isEqualToString:HKQuantityTypeIdentifierHeight]) {
        return @[@"cm", @"m", @"ft", @"in"];
    } else if ([identifier isEqualToString:HKQuantityTypeIdentifierBodyMass] ||
               [identifier isEqualToString:HKQuantityTypeIdentifierLeanBodyMass]) {
        return @[@"kg", @"g", @"lb", @"oz"];
    } else if ([identifier isEqualToString:HKQuantityTypeIdentifierBodyTemperature]) {
        return @[@"°C", @"°F"];
    } else if ([identifier isEqualToString:HKQuantityTypeIdentifierBloodPressureSystolic] ||
               [identifier isEqualToString:HKQuantityTypeIdentifierBloodPressureDiastolic]) {
        return @[@"mmHg"];
    } else if ([identifier isEqualToString:HKQuantityTypeIdentifierBloodGlucose]) {
        return @[@"mg/dL", @"mmol/L"];
    } else if ([identifier isEqualToString:HKQuantityTypeIdentifierOxygenSaturation] ||
               [identifier isEqualToString:HKQuantityTypeIdentifierBodyFatPercentage]) {
        return @[@"%"];
    } else if ([identifier isEqualToString:HKQuantityTypeIdentifierRespiratoryRate]) {
        return @[@"breaths/min"];
    }
    
    return @[];
}

RCT_EXPORT_METHOD(requestWriteOnlyAuthorization:(NSArray *)writeTypes
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    NSLog(@"✏️ [Native] requestWriteOnlyAuthorization iniciado");
    NSLog(@"✏️ [Native] iOS Version: %@", [[UIDevice currentDevice] systemVersion]);
    NSLog(@"✏️ [Native] HealthKit Available: %@", [HKHealthStore isHealthDataAvailable] ? @"YES" : @"NO");
    
    // Verificar estado do app
    UIApplicationState appState = [[UIApplication sharedApplication] applicationState];
    NSString *appStateString;
    switch (appState) {
        case UIApplicationStateActive:
            appStateString = @"Active";
            break;
        case UIApplicationStateInactive:
            appStateString = @"Inactive";
            break;
        case UIApplicationStateBackground:
            appStateString = @"Background";
            break;
        default:
            appStateString = @"Unknown";
            break;
    }
    NSLog(@"✏️ [Native] App State: %@", appStateString);
    
    if (appState != UIApplicationStateActive) {
        NSLog(@"❌ [Native] App não está ativo, estado: %@", appStateString);
        reject(@"ERR_APP_STATE", @"App must be active to request authorization", nil);
        return;
    }
    
    if (![HKHealthStore isHealthDataAvailable]) {
        NSLog(@"❌ [Native] HealthKit não disponível");
        reject(@"ERR_HEALTHKIT_UNAVAILABLE", @"HealthKit is not available on this device", nil);
        return;
    }
    
    if (!writeTypes || ![writeTypes isKindOfClass:[NSArray class]]) {
        NSLog(@"❌ [Native] writeTypes inválido");
        reject(@"ERR_INVALID_INPUT", @"Invalid writeTypes array", nil);
        return;
    }
    
    NSLog(@"✏️ [Native] writeTypes: %@", writeTypes);
    
    NSMutableSet *typesToWrite = [[NSMutableSet alloc] init];
    NSMutableArray *failedWriteTypes = [[NSMutableArray alloc] init];
    
    for (NSString *identifier in writeTypes) {
        if (![identifier isKindOfClass:[NSString class]] || identifier.length == 0) {
            [failedWriteTypes addObject:identifier ?: @"null"];
            continue;
        }
        
        NSLog(@"🔍 [Native] Processando writeType: %@", identifier);
        
        @try {
            HKObjectType *type = [self getHKObjectTypeFromString:identifier];
            if (type) {
                NSLog(@"✅ [Native] Tipo reconhecido: %@", type.identifier);
                [typesToWrite addObject:type];
            } else {
                NSLog(@"❌ [Native] Tipo não reconhecido: %@", identifier);
                [failedWriteTypes addObject:identifier];
            }
        } @catch (NSException *exception) {
            NSLog(@"❌ [Native] Exception ao processar tipo %@: %@", identifier, exception.reason);
            [failedWriteTypes addObject:identifier];
        }
    }
    
    // Log failed types for debugging
    if (failedWriteTypes.count > 0) {
        NSLog(@"Failed to process write types: %@", [failedWriteTypes componentsJoinedByString:@", "]);
    }
    
    // If no valid types to request, return success
    if (typesToWrite.count == 0) {
        NSLog(@"⚠️ [Native] Nenhum tipo válido para autorizar escrita");
        resolve(@(YES));
        return;
    }
    
    NSLog(@"✏️ [Native] Tipos válidos para autorizar escrita: %@", typesToWrite);
    
    // Check current authorization status before requesting
    NSMutableSet *typesNeedingAuthorization = [[NSMutableSet alloc] init];
    for (HKObjectType *type in typesToWrite) {
        HKAuthorizationStatus currentStatus = [self.healthStore authorizationStatusForType:type];
        NSLog(@"🔍 [Native] %@ - Status atual: %ld", type.identifier, (long)currentStatus);
        
        if (currentStatus == HKAuthorizationStatusNotDetermined) {
            [typesNeedingAuthorization addObject:type];
            NSLog(@"✏️ [Native] %@ precisa de autorização de escrita", type.identifier);
        } else if (currentStatus == HKAuthorizationStatusSharingAuthorized) {
            NSLog(@"✅ [Native] %@ já autorizado para escrita", type.identifier);
        } else {
            NSLog(@"❌ [Native] %@ negado ou restrito para escrita", type.identifier);
        }
    }
    
    // If no types need authorization, return success
    if (typesNeedingAuthorization.count == 0) {
        NSLog(@"✅ [Native] Todos os tipos já estão autorizados para escrita");
        resolve(@(YES));
        return;
    }
    
    NSLog(@"✏️ [Native] Tipos que precisam de autorização de escrita: %@", typesNeedingAuthorization);
    
    // Ensure we're on the main thread for authorization requests
    if ([NSThread isMainThread]) {
        NSLog(@"✏️ [Native] Executando na main thread");
        @try {
            NSLog(@"✏️ [Native] Chamando requestAuthorizationToShareTypes (apenas escrita)...");
            NSLog(@"✏️ [Native] writeTypes count: %lu", (unsigned long)typesNeedingAuthorization.count);
            NSLog(@"✏️ [Native] readTypes: [NSSet set] (vazio)");
            
            // Pass empty set for read types to request write-only access
            [self.healthStore requestAuthorizationToShareTypes:typesNeedingAuthorization
                                                     readTypes:[NSSet set]
                                                    completion:^(BOOL success, NSError *error) {
                if (success) {
                    NSLog(@"✅ [Native] Autorização de escrita bem-sucedida");
                    resolve(@(YES));
                } else {
                    NSLog(@"❌ [Native] Autorização de escrita falhou: %@", error.localizedDescription);
                    NSString *errorMessage = error ? error.localizedDescription : @"Failed to authorize HealthKit for writing";
                    reject(@"ERR_AUTHORIZATION_FAILED", errorMessage, error);
                }
            }];
        } @catch (NSException *exception) {
            NSLog(@"❌ [Native] Exception durante autorização de escrita: %@", exception.reason);
            reject(@"ERR_AUTHORIZATION_EXCEPTION", exception.reason, nil);
        }
    } else {
        NSLog(@"✏️ [Native] Despachando para main thread");
        dispatch_async(dispatch_get_main_queue(), ^{
            @try {
                NSLog(@"✏️ [Native] Chamando requestAuthorizationToShareTypes (apenas escrita) na main thread...");
                NSLog(@"✏️ [Native] writeTypes count: %lu", (unsigned long)typesNeedingAuthorization.count);
                NSLog(@"✏️ [Native] readTypes: [NSSet set] (vazio)");
                
                // Pass empty set for read types to request write-only access
                [self.healthStore requestAuthorizationToShareTypes:typesNeedingAuthorization
                                                         readTypes:[NSSet set]
                                                        completion:^(BOOL success, NSError *error) {
                    if (success) {
                        NSLog(@"✅ [Native] Autorização de escrita bem-sucedida");
                        resolve(@(YES));
                    } else {
                        NSLog(@"❌ [Native] Autorização de escrita falhou: %@", error.localizedDescription);
                        NSString *errorMessage = error ? error.localizedDescription : @"Failed to authorize HealthKit for writing";
                        reject(@"ERR_AUTHORIZATION_FAILED", errorMessage, error);
                    }
                }];
            } @catch (NSException *exception) {
                NSLog(@"❌ [Native] Exception durante autorização de escrita: %@", exception.reason);
                reject(@"ERR_AUTHORIZATION_EXCEPTION", exception.reason, nil);
            }
        });
    }
}

RCT_EXPORT_METHOD(diagnoseAuthorizationRequirements:(NSArray *)types
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    
    NSLog(@"🔍 [Native] diagnoseAuthorizationRequirements iniciado");
    
    if (![HKHealthStore isHealthDataAvailable]) {
        reject(@"ERR_HEALTHKIT_UNAVAILABLE", @"HealthKit is not available on this device", nil);
        return;
    }
    
    if (!types || ![types isKindOfClass:[NSArray class]]) {
        reject(@"ERR_INVALID_INPUT", @"Invalid types array", nil);
        return;
    }
    
    NSMutableArray *results = [[NSMutableArray alloc] init];
    
    for (NSString *identifier in types) {
        if (![identifier isKindOfClass:[NSString class]] || identifier.length == 0) {
            continue;
        }
        
        @try {
            HKObjectType *type = [self getHKObjectTypeFromString:identifier];
            if (type) {
                // Check current authorization status
                HKAuthorizationStatus readStatus = [self.healthStore authorizationStatusForType:type];
                HKAuthorizationStatus writeStatus = [self.healthStore authorizationStatusForType:type];
                
                NSDictionary *result = @{
                    @"identifier": identifier,
                    @"readStatus": @(readStatus),
                    @"writeStatus": @(writeStatus),
                    @"requiresWriteForRead": @(readStatus == HKAuthorizationStatusSharingDenied && writeStatus == HKAuthorizationStatusSharingAuthorized)
                };
                
                [results addObject:result];
                NSLog(@"🔍 [Native] %@ - Read: %ld, Write: %ld", identifier, (long)readStatus, (long)writeStatus);
            }
        } @catch (NSException *exception) {
            NSLog(@"❌ [Native] Exception ao diagnosticar %@: %@", identifier, exception.reason);
        }
    }
    
    resolve(results);
}

@end 