import bureau_id_fraud_sdk
import React

@objc(FraudNativeModule)
class FraudNativeModule: RCTEventEmitter, bureau_id_fraud_sdk.BureauFingerPrintDelegate {
  
  private var resultResolve: RCTPromiseResolveBlock?
  
  override init() {
    super.init()
  }

  func onFinished(result: Bool, _ submitRespose: bureau_id_fraud_sdk.BureauSubmitResponse) {
    guard let resultResolve = resultResolve else {
      return
    }

    if result {
      var responseMap: [String: Any] = [
        "message": "Success",
        "eventId": submitRespose.eventId,
      ]

      if let action = submitRespose.action {
        responseMap["action"] = action
      }

      if let iv = submitRespose.iv {
        responseMap["iv"] = iv
      }

      if let insights = submitRespose.insights {
        do {
          let encoder = JSONEncoder()
          let jsonData = try encoder.encode(insights)
          if let insightsMap = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {
            responseMap["insights"] = insightsMap
          }
        } catch {
          resultResolve(["message": "Error: Insights are malformed", "eventId": submitRespose.eventId])
          return
        }
      }

      resultResolve(responseMap)
    } else {
      let message = submitRespose.error?.errorDescription ?? "Unknown error"
      resultResolve(["message": "Error: \(message)", "eventId": submitRespose.eventId])
    }
  }

  @objc(submitDeviceIntelligence:withRejecter:)
  func submitDeviceIntelligence(resolve:@escaping RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock){
    resultResolve = resolve
    DispatchQueue.main.async {
      BureauAPI.shared.fingerprintDelegate = self
      BureauAPI.shared.submit()
    }
  }
  
  @objc(asyncSubmitDeviceIntelligence:withRejecter:)
  func asyncSubmitDeviceIntelligence(resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) {
    DispatchQueue.main.async {
      do {
        let eventId = BureauAPI.shared.asyncSubmit()
        resolve(eventId)
      } catch {
        reject("ASYNC_SUBMIT_FAILED", error.localizedDescription, error)
      }
    }
  }

  @objc(initDeviceIntelligence:env:enableSmartInsightFetch:)
  func initDeviceIntelligence(clientId: String, env: String, enableSmartInsightFetch: Bool) {
    var mode = Environment.production
    switch(env.lowercased()){
    case "production", "prod":
      mode = Environment.production
    default:
      mode = Environment.stage
    }
    DispatchQueue.main.async {
      let config = BureauConfig(
        credentialID: clientId,
        environment: mode,
        enableSmartInsightFetch: enableSmartInsightFetch,
        enableDebugLog: true
      )
      BureauAPI.shared.configure(config: config)
    }
  }

  @objc(setUserId:)
  func setUserId(userId:String){
    print("userId-->",userId)
    DispatchQueue.main.async {
      BureauAPI.shared.setUserID(userId)
    }
  }

  @objc(setFlow:)
  func setFlow(flow:String){
    DispatchQueue.main.async {
      BureauAPI.shared.setFlow(flow)
    }
  }

  @objc(getUserId:withRejecter:)
  func getUserId(resolve: @escaping RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
    resolve("")
  }
  

  @objc(isInitialized:withRejecter:)
  func isInitialized(resolve: @escaping RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
    resolve(BureauAPI.shared.isSDKInitializationSuccess())
  }
  
  @objc(setMetaInfo:)
  func setMetaInfo(json: [String: Any]) {
    var data: [String: String] = [:]
        for (key, value) in json {
          if let str = value as? String {
            data[key] = str
          } else if value is NSNull {
            data[key] = ""
          } else {
            data[key] = "\(value)"
          }
        }

        DispatchQueue.main.async {
          BureauAPI.shared.setMetaInfo(data)
        }
  }

}
