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

import NevisMobileAuthentication

actor OutOfBandRegistrationOperation: UserInteractionOperation {
	typealias T = AuthorizationProvider

	// MARK: Properties

	let registration: OutOfBandRegistration
	private(set) var state: OperationState
	let accountSelector: AccountSelector? = nil
	let authenticatorSelector: AuthenticatorSelector
	private(set) var pinEnroller: PinEnroller?
	let passwordEnroller: PasswordEnroller?
	let pinUserVerifier: PinUserVerifier? = nil
	let passwordUserVerifier: PasswordUserVerifier? = nil
	let biometricUserVerifier: BiometricUserVerifier
	let devicePasscodeUserVerifier: DevicePasscodeUserVerifier
	private(set) var onSuccess: SuccessHandler
	private(set) var onError: ErrorHandler

	// MARK: Initialization

	init(operationId: String, method: ReactMethod, registration: OutOfBandRegistration) {
		self.state = NoOperationState()
		self.authenticatorSelector = AuthenticatorSelectorImpl(operationId: operationId)
		self.pinEnroller = PinEnrollerImpl(operationId: operationId, pinPolicy: nil)
		self.passwordEnroller = PasswordEnrollerImpl(operationId: operationId)
		self.biometricUserVerifier = BiometricUserVerifierImpl(operationId: operationId)
		self.devicePasscodeUserVerifier = DevicePasscodeUserVerifierImpl(operationId: operationId)
		self.onSuccess = OnSuccessImpl(operationId: operationId, method: method).onSuccess
		self.onError = OnErrorImpl(operationId: operationId, method: method).onError
		self.registration = registration
	}

	// MARK: Public Interface

	@discardableResult
	func update(operationId: String, method: ReactMethod, pinPolicy: PinPolicy?) -> OutOfBandRegistrationOperation {
		pinEnroller = PinEnrollerImpl(operationId: operationId, pinPolicy: pinPolicy)
		onSuccess = OnSuccessImpl(operationId: operationId, method: method).onSuccess
		onError = OnErrorImpl(operationId: operationId, method: method).onError
		return self
	}

	// MARK: UserInteractionOperation

	func update(state: UserInteractionState) -> any UserInteractionOperation {
		self.state = state
		return self
	}
}
