#import <ZSM/ZSMClient.h>

@class RelyingParty;

NS_ASSUME_NONNULL_BEGIN

@interface UMFAClient : ZSMClient

#pragma mark - Passkey Support

/**
 * Check if passkeys are supported on this device.
 *
 * Passkeys require iOS 16.0 or later AND passkeyRpId must be configured.
 * When passkeys are not supported:
 * - userVerification="required" will fail with an error
 * - userVerification="preferred"/"discouraged"/"prevented" will use MPC-only
 *
 * @return YES if passkeys are supported, NO otherwise.
 */
- (BOOL)isPasskeySupported
NS_SWIFT_NAME(isPasskeySupported());

/**
 * Get the reason why passkeys are not supported (for debugging/user messaging).
 *
 * @return A human-readable string explaining why passkeys aren't supported, or nil if supported.
 */
- (NSString * _Nullable)passkeyNotSupportedReason
NS_SWIFT_NAME(passkeyNotSupportedReason());

#pragma mark - Registration and initialization

- (instancetype)init NS_UNAVAILABLE;

- (instancetype)initWithConfig:(ZSMConfig *)config relyingParty:(RelyingParty *)relyingParty
NS_SWIFT_NAME(init(_:relyingParty:));

/**
 * Checks if a user is enrolled with WebAuthn.
 * @param userId The identifier of the user.
 * @param completion Callback returning enrollment details if the user is enrolled, otherwise an error.
 */
- (void)checkEnrollment:(NSString *)userId
             completion:(ZSMJSONCompletion)completion
NS_SWIFT_NAME(checkEnrollment(userId:completion:));

/**
 * Initiates the enrollment process for a user.
 * @param userId The identifier of the user.
 * @param completion Callback returning a token if enrollment is successful, otherwise an error.
 * @note Defaults to userVerification="prevented" (MPC-only). Use enroll:userVerification:completion: for PasskeysPlus.
 */
- (void)enroll:(NSString *)userId
    completion:(ZSMJSONCompletion)completion
NS_SWIFT_NAME(enroll(userId:completion:));

/**
 * Initiates the enrollment process for a user with WebAuthn user verification control.
 * @param userId The identifier of the user.
 * @param userVerification WebAuthn user verification requirement:
 *        - "required": Create PasskeysPlus (passkey + MPC), MUST perform user verification (biometric/PIN)
 *        - "preferred": Create PasskeysPlus (passkey + MPC), prefer user verification but allow without
 *        - "discouraged": Create MPC-only (no passkey)
 *        - "prevented": Create MPC-only (no passkey) - same as discouraged
 * @param completion Callback returning a token if enrollment is successful, otherwise an error.
 * @note MPC storage encryption is controlled by config.requiresBiometrics, not per-operation.
 */
- (void)enroll:(NSString *)userId
userVerification:(NSString *)userVerification
    completion:(ZSMJSONCompletion)completion
NS_SWIFT_NAME(enroll(userId:userVerification:completion:));

/**
 * Authenticates a user via WebAuthn.
 * @param userId The identifier of the user.
 * @param completion Callback returning authentication details or an error if authentication fails.
 * @note Defaults to userVerification="prevented" (MPC-only). Use authenticate:userVerification:completion: for PasskeysPlus.
 */
- (void)authenticate:(NSString *)userId
          completion:(ZSMJSONCompletion)completion
NS_SWIFT_NAME(authenticate(userId:completion:));

/**
 * Authenticates a user with userVerification preference control.
 *
 * userVerification controls whether to USE passkeys dynamically:
 * - "required": Use passkey if available, otherwise fail
 * - "preferred": Use passkey if available, otherwise use MPC (default for authenticate)
 * - "discouraged": Always use MPC-only, even if passkey exists (allows runtime toggle)
 * - "prevented": Always use MPC-only, even if passkey exists - same as discouraged
 *
 * config.requiresBiometrics controls MPC storage encryption (separate concept).
 *
 * @param userId The identifier of the user.
 * @param userVerification User verification preference: "required", "preferred", "discouraged", or "prevented".
 * @param completion Callback returning authentication details or an error if authentication fails.
 */
- (void)authenticate:(NSString *)userId
  userVerification:(NSString *)userVerification
          completion:(ZSMJSONCompletion)completion
NS_SWIFT_NAME(authenticate(userId:userVerification:completion:));

/**
 * Check if user has any credentials enrolled (local check, no API call).
 *
 * This is a convenience method for quickly checking if a user is enrolled.
 * For detailed state information, use getCredentialState instead.
 *
 * @param userId The user identifier.
 * @return true if user has MPC or passkey credentials, false otherwise.
 */
- (BOOL)isUserEnrolled:(NSString *)userId
NS_SWIFT_NAME(isUserEnrolled(userId:));

/**
 * Get the credential state for a user (local check, no API call).
 *
 * Returns one of:
 * - CredentialStateNone: No credentials enrolled
 * - CredentialStateMPCOnly: Only MPC credential exists
 * - CredentialStatePasskeyOnly: Only passkey credential exists
 * - CredentialStateBoth: Both MPC and passkey credentials exist (PasskeysPlus)
 *
 * @param userId The user identifier.
 * @return The user's credential state.
 */
- (NSInteger)getCredentialState:(NSString *)userId
NS_SWIFT_NAME(getCredentialState(userId:));

/**
 * Get the credential state for a user from the SERVER (source of truth).
 *
 * This queries the server to determine what credentials exist, which is useful for:
 * - Cross-device scenarios where credentials might exist on server but not locally
 * - Synced passkeys (e.g., iCloud Keychain) where local state may not reflect server state
 * - Migration scenarios where you need authoritative credential information
 *
 * Returns via callback one of:
 * - 0 (CredentialStateNone): No credentials on server
 * - 1 (CredentialStateMPCOnly): Only MPC credential on server
 * - 2 (CredentialStatePasskeyOnly): Only passkey credential on server
 * - 3 (CredentialStateBoth): Both MPC and passkey credentials on server (PasskeysPlus)
 *
 * @param userId The user identifier.
 * @param completion Callback with credential state (NSInteger) or error.
 */
- (void)getServerCredentialState:(NSString *)userId
                      completion:(void (^)(NSInteger state, ZSMError * _Nullable error))completion
NS_SWIFT_NAME(getServerCredentialState(userId:completion:));

/**
 * Get a human-readable description of a credential state.
 *
 * @param state The credential state (from getCredentialState)
 * @return A descriptive string (e.g., "Both credentials (PasskeysPlus complete)")
 */
- (NSString *)getStateDescription:(NSInteger)state
NS_SWIFT_NAME(getStateDescription(state:));

/**
 * Add MPC credential to an existing identity that only has passkey credential (migration scenario).
 *
 * This method enables migrating users from passkey-only to PasskeysPlus (both credentials).
 * It will fail if the user doesn't have an existing passkey credential.
 *
 * CRITICAL: This retrieves the identity_id from the existing passkey credential,
 * then creates an MPC credential using that same identity_id.
 *
 * @param userId The identifier of the user.
 * @param completion Callback with MPC credential result, metadata, or error.
 */
- (void)addMpcToPasskeyUser:(NSString *)userId
                 completion:(ZSMJSONCompletion)completion
NS_SWIFT_NAME(addMpcToPasskeyUser(userId:completion:));

/**
 * Unenrolls the UMFA client current user, clearing stored credentials and identity mappings.
 * @param userId The identifier of the user.
 * @param completion Callback invoked when the reset is complete.
 */
- (void)unenroll:(NSString *)userId completion:(ZSMBooleanCompletion)completion
NS_SWIFT_NAME(unenroll(userId:completion:));

/**
 * Lists all registered users (userIds) that have WebAuthn credentials stored locally.
 *
 * This method properly implements the separation of concerns:
 * 1. Calls FIDO2Client to get all consumer_id UUIDs (MPC-level identifiers)
 * 2. Uses RelyingParty's identity mappings to convert UUIDs back to userIds
 * 3. Returns only the userIds that have valid mappings
 *
 * @return Array of user identifiers (userIds) that have registered credentials
 */
- (NSArray<NSString *> *)listRegisteredUsers
NS_SWIFT_NAME(listRegisteredUsers());

/**
 * Check all enrollment information for a specific user.
 *
 * Returns complete enrollment data including identity_id, credential state, and flags.
 * This matches the Android and JavaScript SDK's checkAllEnrollments method.
 *
 * @param userId The user identifier
 * @return NSDictionary containing enrollment information, or error if user not found
 */
- (NSDictionary *)checkAllEnrollments:(NSString *)userId
NS_SWIFT_NAME(checkAllEnrollments(userId:));

/**
 * Check all enrollment information for a specific user, optionally consulting the server.
 *
 * This is the browser-aligned variant. It returns normalized enrollment data and,
 * when needed or explicitly requested, merges authoritative server enrollment state.
 *
 * @param userId The user identifier
 * @param forceRemoteCheck If YES, always consult server enrollment state before returning
 * @param completion Callback with normalized enrollment information or error
 */
- (void)checkAllEnrollments:(NSString *)userId
         forceRemoteCheck:(BOOL)forceRemoteCheck
             completion:(ZSMJSONCompletion)completion
NS_SWIFT_NAME(checkAllEnrollments(userId:forceRemoteCheck:completion:));

/**
 * Remove all stored credentials for a specific user (for testing purposes).
 *
 * This clears all local credential state including passkey and MPC credentials.
 * Useful for testing different enrollment scenarios without reinstalling the app.
 *
 * @param userId The user identifier whose credentials should be removed
 */
- (void)removeAllCredentials:(NSString *)userId
NS_SWIFT_NAME(removeAllCredentials(userId:));

/// This method is intentionally unavailable in UMFAClient.
/// Do not call this from Swift. Use proper lifecycle methods.
- (void)unbindWithCompletion:(nonnull ZSMBooleanCompletion)completion NS_UNAVAILABLE;
- (void)unbindForUser:(nonnull NSString *)user withCompletion:(nonnull ZSMBooleanCompletion)completion NS_UNAVAILABLE;

@end

NS_ASSUME_NONNULL_END
