//
// Copyright © 2024 Nevis Security AG. All rights reserved.
//

import NevisMobileAuthentication

extension AuthCloudApiRegistration {
	func configure(by authCloudApiRegistrationMessage: AuthCloudApiRegistrationMessage, operation authCloudApiRegistrationOperation: AuthCloudApiRegistrationOperation) -> AuthCloudApiRegistration {
		if let enrollResponse = authCloudApiRegistrationMessage.enrollResponse {
			self.enrollResponse(enrollResponse)
		}
		else if let appLinkUri = authCloudApiRegistrationMessage.appLinkUri {
			self.appLinkUri(appLinkUri)
		}

		if let deviceInformation = authCloudApiRegistrationMessage.deviceInformation {
			self.deviceInformation(deviceInformation)
		}

		if let allowDevicePasscodeAsFallback = authCloudApiRegistrationMessage.allowDevicePasscodeAsFallback {
			self.allowDevicePasscodeAsFallback(allowDevicePasscodeAsFallback)
		}

		if let invalidateOnNewOsBiometrics = authCloudApiRegistrationMessage.invalidateOnNewOsBiometrics {
			self.invalidateOnNewOsBiometrics(invalidateOnNewOsBiometrics)
		}

		if let requestHeaders = authCloudApiRegistrationMessage.requestHeaders {
			self.requestHeaders(requestHeaders.namesAndValues)
		}

		if authCloudApiRegistrationMessage.authenticatorSelectorProvided {
			authenticatorSelector(authCloudApiRegistrationOperation.authenticatorSelector)
		}

		if authCloudApiRegistrationMessage.pinEnrollerProvided {
			pinEnroller(authCloudApiRegistrationOperation.pinEnroller)
		}

		if authCloudApiRegistrationMessage.passwordEnrollerProvided {
			passwordEnroller(authCloudApiRegistrationOperation.passwordEnroller)
		}

		if authCloudApiRegistrationMessage.biometricUserVerifierProvided {
			biometricUserVerifier(authCloudApiRegistrationOperation.biometricUserVerifier)
		}

		if authCloudApiRegistrationMessage.devicePasscodeUserVerifierProvided {
			devicePasscodeUserVerifier(authCloudApiRegistrationOperation.devicePasscodeUserVerifier)
		}

		if authCloudApiRegistrationMessage.onSuccessProvided {
			onSuccess { authCloudApiRegistrationOperation.onSuccess(nil) }
		}

		if authCloudApiRegistrationMessage.onErrorProvided {
			onError(authCloudApiRegistrationOperation.onError)
		}

		return self
	}
}

extension Authentication {
	func configure(by authenticationMessage: AuthenticationMessage, operation authenticationOperation: AuthenticationOperation) -> Authentication {
		if let username = authenticationMessage.username {
			self.username(username)
		}

		if let typedSessionProvider = authenticationMessage.sessionProvider {
			sessionProvider(typedSessionProvider.wrapped)
		}

		if let retryPolicy = authenticationMessage.retryPolicy {
			retryPolicyObtainingAuthorizationProvider(retryPolicy.wrapped)
		}

		if let requestHeaders = authenticationMessage.requestHeaders {
			self.requestHeaders(requestHeaders.namesAndValues)
		}

		if authenticationMessage.authenticatorSelectorProvided {
			authenticatorSelector(authenticationOperation.authenticatorSelector)
		}

		if authenticationMessage.pinUserVerifierProvided {
			pinUserVerifier(authenticationOperation.pinUserVerifier)
		}

		if authenticationMessage.passwordUserVerifierProvided {
			passwordUserVerifier(authenticationOperation.passwordUserVerifier)
		}

		if authenticationMessage.biometricUserVerifierProvided {
			biometricUserVerifier(authenticationOperation.biometricUserVerifier)
		}

		if authenticationMessage.devicePasscodeUserVerifierProvided {
			devicePasscodeUserVerifier(authenticationOperation.devicePasscodeUserVerifier)
		}

		if authenticationMessage.onSuccessProvided {
			onSuccess { authenticationOperation.onSuccess($0) }
		}

		if authenticationMessage.onErrorProvided {
			onError(authenticationOperation.onError)
		}

		return self
	}
}

extension Deregistration {
	func configure(by deregistrationMessage: DeregistrationMessage, operation deregistrationOperation: DeregistrationOperation) ->
		Deregistration
	{
		if let username = deregistrationMessage.username {
			self.username(username)
		}

		if let aaid = deregistrationMessage.aaid {
			self.aaid(aaid)
		}

		if let typedAuthorizationProvider = deregistrationMessage.authorizationProvider {
			authorizationProvider(typedAuthorizationProvider.wrapped)
		}

		if let requestHeaders = deregistrationMessage.requestHeaders {
			self.requestHeaders(requestHeaders.namesAndValues)
		}

		if deregistrationMessage.onSuccessProvided {
			onSuccess(deregistrationOperation.onSuccess)
		}

		if deregistrationMessage.onErrorProvided {
			onError(deregistrationOperation.onError)
		}

		return self
	}
}

extension DeviceInformationChange {
	func configure(by deviceInformationChangeMessage: DeviceInformationChangeMessage, operation deviceInformationChangeOperation: DeviceInformationChangeOperation) -> DeviceInformationChange {
		if let name = deviceInformationChangeMessage.name {
			self.name(name)
		}

		if let fcmRegistrationToken = deviceInformationChangeMessage.fcmRegistrationToken, !fcmRegistrationToken.isEmpty {
			self.fcmRegistrationToken(fcmRegistrationToken)
		}

		if let disablePushNotifications = deviceInformationChangeMessage.disablePushNotifications, disablePushNotifications {
			self.disablePushNotifications()
		}

		if let retryPolicy = deviceInformationChangeMessage.retryPolicy {
			self.retryPolicy(retryPolicy.wrapped)
		}

		if let requestHeaders = deviceInformationChangeMessage.requestHeaders {
			self.requestHeaders(requestHeaders.namesAndValues)
		}

		if deviceInformationChangeMessage.onSuccessProvided {
			onSuccess(deviceInformationChangeOperation.onSuccess)
		}

		if deviceInformationChangeMessage.onErrorProvided {
			onError(deviceInformationChangeOperation.onError)
		}

		return self
	}
}

extension DeviceInformationCheck {
	func configure(by deviceInformationCheckMessage: DeviceInformationCheckMessage) -> DeviceInformationCheck {
		if let requestHeaders = deviceInformationCheckMessage.requestHeaders {
			self.requestHeaders(requestHeaders.namesAndValues)
		}

		if deviceInformationCheckMessage.onResultProvided {
			onResult { result in
				let message = DeviceInformationCheckResultMessage(operationId: deviceInformationCheckMessage.operationId,
				                                                  result: result)
				MethodChannelHandler.shared.resolve(method: .deviceInformationCheck, message: message)
			}
		}

		return self
	}
}

extension DeviceInformationSync {
	func configure(by deviceInformationSyncMessage: DeviceInformationSyncMessage) -> DeviceInformationSync {
		if let requestHeaders = deviceInformationSyncMessage.requestHeaders {
			self.requestHeaders(requestHeaders.namesAndValues)
		}

		if let mismatches = deviceInformationSyncMessage.mismatches {
			self.mismatches(mismatches.map(\.wrapped))
		}

		if deviceInformationSyncMessage.onResultProvided {
			onResult { result in
				let message = DeviceInformationSyncResultMessage(operationId: deviceInformationSyncMessage.operationId,
				                                                 result: result)
				MethodChannelHandler.shared.resolve(method: .deviceInformationSync, message: message)
			}
		}

		return self
	}
}

extension NevisMobileAuthentication.OutOfBandOperation {
	func configure(by oobOperationMessage: OutOfBandOperationMessage, operation oobOperation: OutOfBandOperation, onRegistration: @escaping (OutOfBandRegistration) -> (), onAuthentication: @escaping (NevisMobileAuthentication.OutOfBandAuthentication) -> ()) -> NevisMobileAuthentication.OutOfBandOperation {
		if let payload = oobOperationMessage.payload {
			self.payload(payload)
		}

		if let requestHeaders = oobOperationMessage.requestHeaders {
			self.requestHeaders(requestHeaders.namesAndValues)
		}

		if oobOperationMessage.onRegistrationProvided {
			self.onRegistration(onRegistration)
		}

		if oobOperationMessage.onAuthenticationProvided {
			self.onAuthentication(onAuthentication)
		}

		if oobOperationMessage.onErrorProvided {
			onError(oobOperation.onError)
		}

		return self
	}
}

extension OutOfBandPayloadDecode {
	func configure(by oobPayloadDecodeMessage: OutOfBandPayloadDecodeMessage, operation oobPayloadDecodeOperation: OutOfBandPayloadDecodeOperation) -> OutOfBandPayloadDecode {
		if let json = oobPayloadDecodeMessage.json {
			self.json(json)
		}

		if let base64UrlEncoded = oobPayloadDecodeMessage.base64UrlEncoded {
			self.base64UrlEncoded(base64UrlEncoded)
		}

		if oobPayloadDecodeMessage.onSuccessProvided {
			onSuccess { oobPayloadDecodeOperation.onSuccess($0) }
		}

		if oobPayloadDecodeMessage.onErrorProvided {
			onError(oobPayloadDecodeOperation.onError)
		}

		return self
	}
}

extension PendingOutOfBandOperations {
	func configure(by pendingOobOperationsMessage: PendingOobOperationsMessage) -> PendingOutOfBandOperations {
		if let requestHeaders = pendingOobOperationsMessage.requestHeaders {
			self.requestHeaders(requestHeaders.namesAndValues)
		}

		if pendingOobOperationsMessage.onResultProvided {
			onResult { result in
				let message = PendingOobOperationsResultMessage(operationId: pendingOobOperationsMessage.operationId,
				                                                result: result)
				MethodChannelHandler.shared.resolve(method: .pendingOutOfBandOperations, message: message)
			}
		}

		return self
	}
}

extension PinChange {
	func configure(by pinChangeMessage: PinChangeMessage, operation pinChangeOperation: PinChangeOperation) -> NevisMobileAuthentication.PinChange {
		if let username = pinChangeMessage.username {
			self.username(username)
		}

		if pinChangeMessage.pinChangerProvided {
			pinChanger(pinChangeOperation.pinChanger)
		}

		if pinChangeMessage.onSuccessProvided {
			onSuccess(pinChangeOperation.onSuccess)
		}

		if pinChangeMessage.onErrorProvided {
			onError(pinChangeOperation.onError)
		}

		return self
	}
}

extension PasswordChange {
	func configure(by passwordChangeMessage: PasswordChangeMessage, operation passwordChangeOperation: PasswordChangeOperation) -> PasswordChange {
		if let username = passwordChangeMessage.username {
			self.username(username)
		}

		if passwordChangeMessage.passwordChangerProvided {
			passwordChanger(passwordChangeOperation.passwordChanger)
		}

		if passwordChangeMessage.onSuccessProvided {
			onSuccess(passwordChangeOperation.onSuccess)
		}

		if passwordChangeMessage.onErrorProvided {
			onError(passwordChangeOperation.onError)
		}

		return self
	}
}

extension Registration {
	func configure(by registrationMessage: RegistrationMessage, operation registrationOperation: RegistrationOperation) -> Registration {
		if let username = registrationMessage.username {
			self.username(username)
		}

		if let serverUrl = registrationMessage.serverUrl, let url = URL(string: serverUrl) {
			self.serverUrl(url)
		}

		if let deviceInformation = registrationMessage.deviceInformation {
			self.deviceInformation(deviceInformation)
		}

		if let typedAuthorizationProvider = registrationMessage.authorizationProvider {
			authorizationProvider(typedAuthorizationProvider.wrapped)
		}

		if let allowDevicePasscodeAsFallback = registrationMessage.allowDevicePasscodeAsFallback {
			self.allowDevicePasscodeAsFallback(allowDevicePasscodeAsFallback)
		}

		if let invalidateOnNewOsBiometrics = registrationMessage.invalidateOnNewOsBiometrics {
			self.invalidateOnNewOsBiometrics(invalidateOnNewOsBiometrics)
		}

		if let requestHeaders = registrationMessage.requestHeaders {
			self.requestHeaders(requestHeaders.namesAndValues)
		}

		if registrationMessage.authenticatorSelectorProvided {
			authenticatorSelector(registrationOperation.authenticatorSelector)
		}

		if registrationMessage.pinEnrollerProvided {
			pinEnroller(registrationOperation.pinEnroller)
		}

		if registrationMessage.passwordEnrollerProvided {
			passwordEnroller(registrationOperation.passwordEnroller)
		}

		if registrationMessage.biometricUserVerifierProvided {
			biometricUserVerifier(registrationOperation.biometricUserVerifier)
		}

		if registrationMessage.devicePasscodeUserVerifierProvided {
			devicePasscodeUserVerifier(registrationOperation.devicePasscodeUserVerifier)
		}

		if registrationMessage.onSuccessProvided {
			onSuccess { registrationOperation.onSuccess(nil) }
		}

		if registrationMessage.onErrorProvided {
			onError(registrationOperation.onError)
		}

		return self
	}
}
