package com.airlock.iam.common.domain.model.authentication;

import com.airlock.iam.common.api.domain.model.authentication.Authentee;
import com.airlock.iam.common.api.domain.model.authentication.AuthenticationResult;
import com.airlock.iam.common.api.domain.model.authentication.factor.AuthenticationFactorUsage;
import com.airlock.iam.common.api.domain.model.user.UserIdentity;
import java.util.List;
import java.util.Optional;

public record AuthenticationResultImpl(
   List<AuthenticationFactorUsage> authenticationFactorUsages,
   UserIdentity userIdentity,
   boolean factorCheckPerformed,
   boolean retryPossible,
   Optional<Authentee> authentee
) implements AuthenticationResult {
   public static AuthenticationResultImpl successfulAuthenticationWithFactorCheck(Authentee authentee, AuthenticationFactorUsage... authenticationFactorUsages) {
      return new AuthenticationResultImpl(List.of(authenticationFactorUsages), authentee.userIdentity(), true, true, Optional.of(authentee));
   }

   public static AuthenticationResultImpl failedAuthenticationWithFactorCheck(
      UserIdentity userIdentity, boolean retryPossible, AuthenticationFactorUsage... authenticationFactorUsages
   ) {
      return new AuthenticationResultImpl(List.of(authenticationFactorUsages), userIdentity, true, retryPossible, Optional.empty());
   }

   public static AuthenticationResultImpl failedAuthenticationWithoutFactorCheck(
      UserIdentity userIdentity, AuthenticationFactorUsage... authenticationFactorUsages
   ) {
      return new AuthenticationResultImpl(List.of(authenticationFactorUsages), userIdentity, false, false, Optional.empty());
   }

   public static AuthenticationResultImpl withUser(AuthenticationResult authResult, Optional<Authentee> user) {
      return new AuthenticationResultImpl(
         authResult.authenticationFactorUsages(), authResult.userIdentity(), authResult.factorCheckPerformed(), authResult.retryPossible(), user
      );
   }

   public static AuthenticationResultImpl withoutRetryAndWithoutAuthneticatedUser(AuthenticationResult authResult) {
      return new AuthenticationResultImpl(
         authResult.authenticationFactorUsages(), authResult.userIdentity(), authResult.factorCheckPerformed(), false, Optional.empty()
      );
   }

   public static AuthenticationResultImpl withIdentity(AuthenticationResult authResult, UserIdentity identity) {
      return new AuthenticationResultImpl(
         authResult.authenticationFactorUsages(), identity, authResult.factorCheckPerformed(), authResult.retryPossible(), authResult.authentee()
      );
   }
}
