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

import com.airlock.iam.base.api.domain.model.mapification.MapifiedValues;
import com.airlock.iam.base.domain.model.mapification.MapifiedValuesBuilder;
import com.airlock.iam.base.misc.collection.IamCollections;
import com.airlock.iam.common.api.domain.model.authmethod.AuthenticationMethod;
import com.airlock.iam.flow.api.domain.model.session.MultiFlowScopedFlowAttribute;
import com.airlock.iam.flow.shared.domain.model.session.AuthenticationMethodMapificationUtils;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

public final class SuccessfulAuthenticationMethods implements MultiFlowScopedFlowAttribute<SuccessfulAuthenticationMethods> {
   private static final String METHODS_KEY = "methods";
   private final List<AuthenticationMethod> authenticationMethods;

   public static SuccessfulAuthenticationMethods initSuccessfulAuthenticationMethods(AuthenticationMethod... methods) {
      return new SuccessfulAuthenticationMethods(List.of(methods));
   }

   public static SuccessfulAuthenticationMethods initSuccessfulAuthenticationMethods(Collection<AuthenticationMethod> methods) {
      return new SuccessfulAuthenticationMethods(methods);
   }

   private SuccessfulAuthenticationMethods(Collection<AuthenticationMethod> methods) {
      this.authenticationMethods = List.copyOf(methods);
   }

   public List<AuthenticationMethod> getAuthenticationMethods() {
      return List.copyOf(this.authenticationMethods);
   }

   public String getDescription() {
      return this.joinedIds();
   }

   public SuccessfulAuthenticationMethods mergeWith(SuccessfulAuthenticationMethods newAttribute) {
      Collection<AuthenticationMethod> merged = IamCollections.mergeCollections(this.authenticationMethods, newAttribute.getAuthenticationMethods());
      return initSuccessfulAuthenticationMethods(merged);
   }

   @Override
   public MapifiedValues mapify() {
      return MapifiedValuesBuilder.mapifiedValues()
         .putIfNotEmpty("methods", AuthenticationMethodMapificationUtils.mapifyAuthenticationMethods(this.authenticationMethods))
         .build();
   }

   public static SuccessfulAuthenticationMethods demapify(MapifiedValues values) {
      return new SuccessfulAuthenticationMethods(values.demapifyList("methods", AuthenticationMethodMapificationUtils::demapifyAuthenticationMethod));
   }

   private String joinedIds() {
      return this.authenticationMethods.stream().map(AuthenticationMethod::getId).collect(Collectors.joining(", "));
   }
}
