#import "BiometricAuth.h"
#import <LocalAuthentication/LocalAuthentication.h>
#import <React/RCTConvert.h>

@implementation BiometricAuth

RCT_EXPORT_MODULE(BiometricAuth);

#pragma mark - isSensorAvailable

RCT_EXPORT_METHOD(isSensorAvailable:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
  LAContext *context = [[LAContext alloc] init];
  NSError *laError = nil;

  BOOL canEvaluate = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&laError];

  if (canEvaluate) {
    NSString *biometryType = [self getBiometryType:context];
    NSDictionary *result = @{
      @"available": @(YES),
      @"biometryType": biometryType
    };
    resolve(result);
  } else {
    NSDictionary *result = @{
      @"available": @(NO),
      @"error": laError.localizedDescription ?: @"Unknown error"
    };
    resolve(result);
  }
}

#pragma mark - authenticate

RCT_EXPORT_METHOD(authenticate:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
  LAContext *context = [[LAContext alloc] init];
  NSString *reason = @"Authenticate using Biometrics";

  [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
          localizedReason:reason
                    reply:^(BOOL success, NSError *error) {
    if (success) {
      // Returning an object instead of a string
      NSDictionary *response = @{
        @"success": @YES,
        @"message": @"Authentication succeeded"
      };
      resolve(response);
    } else {
      NSDictionary *errorResponse = @{
        @"success": @NO,
        @"error": error.localizedDescription
      };
      resolve(errorResponse);
    }
  }];
}

#pragma mark - getBiometricType

RCT_EXPORT_METHOD(getBiometricType:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
  LAContext *context = [[LAContext alloc] init];

  if (@available(iOS 11.0, *)) {
    NSDictionary *response;
    if (context.biometryType == LABiometryTypeFaceID) {
      response = @{@"biometryType": @"FaceID", @"available": @YES};
    } else if (context.biometryType == LABiometryTypeTouchID) {
      response = @{@"biometryType": @"TouchID", @"available": @YES};
    } else {
      response = @{@"biometryType": @"None", @"available": @NO, @"error": @"No biometric hardware available"};
    }
    resolve(response); // ✅ Always calling resolve, even if no biometrics are available.
  } else {
    NSDictionary *response = @{@"biometryType": @"TouchID", @"available": @YES};
    resolve(response);
  }
}


#pragma mark - simplePrompt

RCT_EXPORT_METHOD(simplePrompt: (NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
  LAContext *context = [[LAContext alloc] init];
  NSString *promptMessage = [RCTConvert NSString:params[@"promptMessage"]];
  NSString *fallbackMessage = [RCTConvert NSString:params[@"fallbackPromptMessage"] ?: @""];
  BOOL allowDeviceCredentials = [RCTConvert BOOL:params[@"allowDeviceCredentials"]];

  LAPolicy policy = LAPolicyDeviceOwnerAuthenticationWithBiometrics;
  if (allowDeviceCredentials) {
    policy = LAPolicyDeviceOwnerAuthentication;
    context.localizedFallbackTitle = fallbackMessage;
  }

  [context evaluatePolicy:policy localizedReason:promptMessage reply:^(BOOL success, NSError *error) {
    if (success) {
      NSDictionary *response = @{@"success": @YES, @"message": @"Authentication succeeded"};
      resolve(response);
    } else {
      NSDictionary *response = @{
        @"success": @NO,
        @"error": error.localizedDescription ?: @"Authentication failed",
        @"code": @(error.code)
      };
      resolve(response);
    }
  }];
}


#pragma mark - cancelAuthentication

RCT_EXPORT_METHOD(cancelAuthentication:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
  if (self.context) {
    [self.context invalidate]; // Properly cancels the ongoing biometric authentication
    self.context = nil; // Reset the context after cancellation

    NSDictionary *response = @{@"success": @YES, @"message": @"Authentication cancelled"};
    resolve(response);
  } else {
    NSDictionary *errorResponse = @{@"success": @NO, @"message": @"No active biometric prompt"};
    resolve(errorResponse);
  }
}

- (NSString *)getBiometryType:(LAContext *)context {
  if (@available(iOS 11.0, *)) {
    if (context.biometryType == LABiometryTypeFaceID) {
      return @"FaceID";
    } else if (context.biometryType == LABiometryTypeTouchID) {
      return @"TouchID";
    }
  }
  return @"None";
}
@end
