//
//  NoPassRNBridgeAuthentificationiOS.swift
//  SdkTest
//
//  Created by Artsiom Shmaenkov on 30.06.21.
//

import Foundation
import React
import NoPassSDKReact

@objc(NoPassRNBridgeAuthentificationiOS)
public class NoPassRNBridgeAuthentificationiOS: NSObject, RCTBridgeModule {
    
    public static func moduleName() -> String! {
        return "NoPassRNBridgeAuthentificationiOS"
    }
    
    public static func requiresMainQueueSetup() -> Bool {
        return true
    }
    
    @objc public static var shared = NoPassRNBridgeAuthentificationiOS()
    
    private override init() {
        super.init()
        NoPassAuthService.shared.delegate = self
    }
    
    @objc public func isHaveActiveAuthSession(_ resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock?) {
        resolver(NoPassAuthService.shared.isHaveAuthSessionNow())
    }
    
    @objc public func getAuthComparisonContent(_ authData: [String : Any], userSeed: String, resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock?) {
        resolver(NoPassAuthService.shared.getAuthComparisonContent(data: authData, userSeed: userSeed))
    }
    
    @objc public func authorize(_ biometricType: String, isScreenLock: Bool) {
        DispatchQueue.main.async {
            if let type = BiometricType(rawValue: biometricType) {
                NoPassAuthService.shared.authorize(enabled2FaMethod: type, isScreenLock: isScreenLock)
            }
        }
    }
    
    @objc public func decline(_ declineTypeString: String, biometricTypeString: String, isScreenLock: Bool, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
        DispatchQueue.main.async {
            guard let declineType = DeclineType(rawValue: declineTypeString) else {
                rejecter("404", NoPassRNBridgeError.declineTypeNotFound.rawValue, nil)
                return
            }
            
            guard let biometricType = BiometricType(rawValue: biometricTypeString) else {
                rejecter("404", NoPassRNBridgeError.biometricTypeNotFound.rawValue, nil)
                return
            }
            
            NoPassAuthService.shared.decline(type:declineType, enabled2FaMethod: biometricType, isScreenLock: isScreenLock)
            resolver([])
        }
    }
    
    func startAuthFlow(authData: [String : Any], biometricType: BiometricType, isScreenLock: Bool) {
        let authModel = NoPassAuthService.shared.startAuthFlow(data: authData,
                                                               enabled2FaMethod: biometricType,
                                                               isScreenLock: isScreenLock)
        EventEmitter.shared.dispatch(name: NoPassRNBridgeEvent.onAuthRequestReceived.rawValue, body: authModel?.toDictionaryForRN())
    }
}

extension NoPassRNBridgeAuthentificationiOS: NoPassAuthServiceDelegate {
    public func onAuthDataChange(comparisonContent: NoPassAuthComparisonContent, authExparedDate: Date, nextUpdate: TimeInterval) {
        var dict = comparisonContent.toDictionary()
        dict["authExparedDate"] = authExparedDate.stringDate(timeZone: TimeZone(abbreviation: "UTC") ?? .current)
        dict["nextUpdate"] = nextUpdate
        EventEmitter.shared.dispatch(name: NoPassRNBridgeEvent.onAuthDataChangedListener.rawValue,
                                     body: dict)
    }
    
    public func onRadiusAuthStart(clientName: String, account: NoPassAccount, authExparedDate: Date) {
        var dict = account.toDictionaryForRN()
        dict["clientName"] = clientName
        dict["authExparedDate"] = authExparedDate.stringDate(timeZone: TimeZone(abbreviation: "UTC") ?? .current)
        EventEmitter.shared.dispatch(name: NoPassRNBridgeEvent.onRadiusAuthDataChangedListener.rawValue,
                                     body: dict)
    }
    
    public func onAuthFinish(error: NopassError?, authStatus: AuthStatus) {
        var dict = Dictionary<AnyHashable, Any?>()
        dict["error"] = error
        dict.merge(authStatus.toDictionaryForRN()) {(current,_) in current }
        EventEmitter.shared.dispatch(name: NoPassRNBridgeEvent.onAuthResultListener.rawValue,
                                     body: dict)
    }
}
