// ios//VADRNBridge.mm
#import "VADRNBridge.h"
#import <React/RCTBridge.h>
#import <React/RCTLog.h>
#import <React/RCTEventEmitter.h>
//#import "VADetection.h" // Import your VADetection library header

// Ensure the protocol is correctly imported or declared
// Assuming the protocol is named 'VADetectionRNDelegate'
@interface VADetectionWrapper : NSObject <VADetectionRNDelegate>

@property (nonatomic, strong) VADetection *VADetection;
@property (nonatomic, strong) NSString *instanceId;
@property (nonatomic, weak) VADRNBridge *bridge;

- (instancetype)initWithInstanceId:(NSString *)instanceId
                         threshold:(float)threshold
                          msWindow:(NSInteger)msWindow
                            bridge:(VADRNBridge *)bridge
                             error:(NSError **)error;

@end

@implementation VADetectionWrapper

- (instancetype)initWithInstanceId:(NSString *)instanceId
                         threshold:(float)threshold
                         msWindow:(NSInteger)msWindow
                            bridge:(VADRNBridge *)bridge
                             error:(NSError **)error
{
    if (self = [super init]) {
        _instanceId = instanceId;
        _bridge = bridge;
        _VADetection = [[VADetection alloc] initWithThreshold:threshold msWindow:msWindow error:error];
        if (*error) {
            return nil;
        }
        _VADetection.delegate = self;
    }
    return self;
}

// Implement the delegate method
- (void)VADetectionDidDetectEvent:(NSDictionary *)eventInfo {
    NSMutableDictionary *mutableEventInfo = [eventInfo mutableCopy];
    mutableEventInfo[@"instanceId"] = self.instanceId;
    [self.bridge sendEventWithName:@"onVADDetectionEvent" body:mutableEventInfo];
}

@end

@interface VADRNBridge ()
@property (nonatomic, strong) NSMutableDictionary *instances;
@end

@implementation VADRNBridge

RCT_EXPORT_MODULE(VADRNBridge);

- (instancetype)init {
    if (self = [super init]) {
        _instances = [NSMutableDictionary new];
    }
    return self;
}

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

+ (BOOL)requiresMainQueueSetup
{
    return YES;
}

RCT_EXPORT_METHOD(createInstance:(NSString *)instanceId threshold:(float)threshold msWindow:(NSInteger)msWindow resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    if (self.instances[instanceId]) {
        reject(@"InstanceExists", [NSString stringWithFormat:@"Instance already exists with ID: %@", instanceId], nil);
        return;
    }

    NSError *error = nil;
    VADetectionWrapper *wrapper = [[VADetectionWrapper alloc] initWithInstanceId:instanceId threshold:threshold msWindow:msWindow bridge:self error:&error];
    if (error) {
        reject(@"CreateError", [NSString stringWithFormat:@"Failed to create instance: %@", error.localizedDescription], nil);
    } else {
        self.instances[instanceId] = wrapper;
        resolve([NSString stringWithFormat:@"Instance created with ID: %@", instanceId]);
    }
}

RCT_EXPORT_METHOD(setVADDetectionLicense:(NSString *)instanceId licenseKey:(NSString *)licenseKey resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    VADetectionWrapper *wrapper = self.instances[instanceId];
    VADetection *instance = wrapper.VADetection;
    BOOL isLicensed = NO;
    if (instance) {
        isLicensed = [instance setLicenseWithLicenseKey:licenseKey];
        NSLog(@"License is valid?: %@", isLicensed ? @"YES" : @"NO");
        resolve(@(isLicensed)); // Wrap BOOL in NSNumber
    } else {
        reject(@"InstanceNotFound", [NSString stringWithFormat:@"No instance found with ID: %@", instanceId], nil);
    }
}

RCT_EXPORT_METHOD(startSilenceVADDetection:(NSString *)instanceId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    VADetectionWrapper *wrapper = self.instances[instanceId];
    VADetection *instance = wrapper.VADetection;
    if (instance) {
        BOOL success = [instance startSilentListening];
        if (success == false) {
            reject(@"StartError", [NSString stringWithFormat:@"Failed to start detection"], nil);
        } else {
            resolve([NSString stringWithFormat:@"Started silent detection for instance: %@", instanceId]);
        }
    } else {
        reject(@"InstanceNotFound", [NSString stringWithFormat:@"No instance found with ID: %@", instanceId], nil);
    }
}

RCT_EXPORT_METHOD(startVADDetection:(NSString *)instanceId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    VADetectionWrapper *wrapper = self.instances[instanceId];
    VADetection *instance = wrapper.VADetection;
    if (instance) {
        BOOL success = [instance startListening];
        if (success == false) {
            reject(@"StartError", [NSString stringWithFormat:@"Failed to start detection"], nil);
        } else {
            resolve([NSString stringWithFormat:@"Started detection for instance: %@", instanceId]);
        }
    } else {
        reject(@"InstanceNotFound", [NSString stringWithFormat:@"No instance found with ID: %@", instanceId], nil);
    }
}

RCT_EXPORT_METHOD(stopSilentVADDetection:(NSString *)instanceId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    VADetectionWrapper *wrapper = self.instances[instanceId];
    VADetection *instance = wrapper.VADetection;
    if (instance) {
        [instance stopSilentListening];
        resolve([NSString stringWithFormat:@"Stopped silent detection for instance: %@", instanceId]);
    } else {
        reject(@"InstanceNotFound", [NSString stringWithFormat:@"No instance found with ID: %@", instanceId], nil);
    }
}

RCT_EXPORT_METHOD(stopVADDetection:(NSString *)instanceId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    VADetectionWrapper *wrapper = self.instances[instanceId];
    VADetection *instance = wrapper.VADetection;
    if (instance) {
        [instance stopListening];
        resolve([NSString stringWithFormat:@"Stopped detection for instance: %@", instanceId]);
    } else {
        reject(@"InstanceNotFound", [NSString stringWithFormat:@"No instance found with ID: %@", instanceId], nil);
    }
}

RCT_EXPORT_METHOD(getVoiceProps:(NSString *)instanceId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    VADetectionWrapper *wrapper = self.instances[instanceId];
    VADetection *instance = wrapper.VADetection;
    
    if (instance) {
        @try {
            NSDictionary *voiceProps = [instance getVoiceProps];
            NSMutableDictionary *result = [NSMutableDictionary dictionary];
            
            result[@"error"] = voiceProps[@"error"] ?: @"No Error"; // Default to "No Error" if nil
            result[@"voiceProbability"] = @([voiceProps[@"voiceProbability"] floatValue]);
            result[@"lastTimeHumanVoiceHeard"] = @([voiceProps[@"lastTimeHumanVoiceHeard"] longLongValue]);
            
            resolve(result);
        } @catch (NSException *exception) {
            reject(@"VoicePropsError", [NSString stringWithFormat:@"Failed to get voice properties: %@", exception.reason], nil);
        }
    } else {
        reject(@"InstanceNotFound", [NSString stringWithFormat:@"No instance found with ID: %@", instanceId], nil);
    }
}

RCT_EXPORT_METHOD(destroyInstance:(NSString *)instanceId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    VADetectionWrapper *wrapper = self.instances[instanceId];
    if (wrapper) {
        [wrapper.VADetection stopListening];
        [self.instances removeObjectForKey:instanceId];
        resolve([NSString stringWithFormat:@"Destroyed instance: %@", instanceId]);
    } else {
        reject(@"InstanceNotFound", [NSString stringWithFormat:@"No instance found with ID: %@", instanceId], nil);
    }
}

/*
RCT_EXPORT_METHOD(getRecordingWav:(NSString *)instanceId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    VADetectionWrapper *wrapper = self.instances[instanceId];
    VADetection *instance = wrapper.VADetection;
    if (instance) {
        NSString *recWavPath = [instance getRecordingWav];
        resolve(recWavPath);
    } else {
        reject(@"InstanceNotFound", [NSString stringWithFormat:@"No instance found with ID: %@", instanceId], nil);
    }
}
*/
// You can add more methods here as needed, ensuring they use the instanceId

@end
