//!important: Intentionally leave out #import "ZSMNativeModule.h", note that it uses externs and should have no problem with the missing import
#import <React/RCTBridgeModule.h>
#import <ZSM/ZSM.h>
#import "generated.h"

@interface ZSMNativeModule : NSObject <RCTBridgeModule>
@property (nonatomic, strong) ZSM *zsm;
@end

@implementation ZSMNativeModule

RCT_EXPORT_MODULE(ZSM);

//TODO: use the same return types in the rust(wasm), kotlin, and ios here, rather than handling in the js client

// Method to return the version string
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getVersionString) {
    return [NSString stringWithUTF8String:ZSM_VERSION];
}

RCT_EXPORT_METHOD(createInstance:(NSDictionary *)config
                         resolver:(RCTPromiseResolveBlock)resolve
                         rejecter:(RCTPromiseRejectBlock)reject) {
    
    ZSMConfig *zsmConfig = [[ZSMConfig alloc] initWithJSON:config];
    zsmConfig.requiresBiometrics = NO; //do not need, have other modules for this.

    [ZSM createInstanceWithConfig:zsmConfig completion:^(ZSM * _Nullable zsm, ZSMError * _Nullable error) {
        if (error) {
            reject(@"zsm_instance_error", error.localizedDescription, nil);
        } else {
            self.zsm = zsm;
            resolve(@{@"success": @YES});
        }
    }];
}

// Method to configure the ZSM instance
RCT_EXPORT_METHOD(configure:(NSDictionary *)config
                   resolver:(RCTPromiseResolveBlock)resolve
                   rejecter:(RCTPromiseRejectBlock)reject) {

    ZSMConfig *zsmConfig = [[ZSMConfig alloc] initWithJSON:config];
    zsmConfig.requiresBiometrics = NO; //do not need, have other modules for this.

    //TODO: temporarily just call the createInstance method again
    [ZSM createInstanceWithConfig:zsmConfig completion:^(ZSM * _Nullable zsm, ZSMError * _Nullable error) {
        if (error) {
            reject(@"ios::configure", error.localizedDescription, nil);
        } else {
            self.zsm = zsm;
            resolve(@{@"success": @YES});
        }
    }];
}

// WebAuthn Create
RCT_EXPORT_METHOD(webauthn_create:(NSDictionary *)options
                         resolver:(RCTPromiseResolveBlock)resolve
                         rejecter:(RCTPromiseRejectBlock)reject) {
    if (!self.zsm) {
        reject(@"ios::webauthn_create", @"ZSM instance is not initialized", nil);
        return;
    }

    [self.zsm webauthnCreateWithOptions:options completion:^(NSDictionary<NSString *, id> * _Nullable credentials, NSDictionary<NSString *, NSString *> * _Nullable metadata, ZSMError * _Nullable error) {
        if (error) {
            reject(@"ios::webauthn_create", error.localizedDescription, nil);
        } else {
            resolve(@{
                @"result": credentials ?: [NSNull null],  // Use NSNull for nil credentials
                @"metadata": metadata ?: [NSNull null]   // Use NSNull for nil metadata
            });
        }
    }];
}

// WebAuthn Get
RCT_EXPORT_METHOD(webauthn_get:(NSDictionary *)options
                      resolver:(RCTPromiseResolveBlock)resolve
                      rejecter:(RCTPromiseRejectBlock)reject) {
    if (!self.zsm) {
        reject(@"ios::webauthn_get", @"ZSM instance is not initialized", nil);
        return;
    }

    [self.zsm webauthnGetWithOptions:options completion:^(NSDictionary<NSString *, id> * _Nullable credentials, NSDictionary<NSString *, NSString *> * _Nullable metadata, ZSMError * _Nullable error) {
        if (error) {
            reject(@"ios::webauthn_get", error.localizedDescription, nil);
        } else {
            resolve(@{
                @"result": credentials ?: [NSNull null],  // Use NSNull for nil credentials
                @"metadata": metadata ?: [NSNull null]   // Use NSNull for nil metadata
            });
        }
    }];
}

// WebAuthn Retrieve
RCT_EXPORT_METHOD(webauthn_retrieve:(NSString *)userIdentifier
                           resolver:(RCTPromiseResolveBlock)resolve
                           rejecter:(RCTPromiseRejectBlock)reject) {

    if (!self.zsm) {
        NSLog( @"webauthn_retrieve zsm missing");
        reject(@"ios::webauthn_retrieve", @"ZSM instance is not initialized", nil);
        return;
    }

    [self.zsm webauthnRetrieveWithCompletion:^(NSDictionary<NSString *, id> * _Nullable credentials, NSDictionary<NSString *, NSString *> * _Nullable metadata, ZSMError * _Nullable error) {
        if (error) {
            reject(@"ios::webauthn_retrieve", error.localizedDescription, nil);
        } else {
            resolve(@{
                @"result": credentials ?: [NSNull null],  // Use NSNull for nil credentials
                @"metadata": metadata ?: [NSNull null]   // Use NSNull for nil metadata
            });
        }
    }];
}

@end
