package com.airlock.iam.common.infrastructure.event;

import com.airlock.iam.common.api.domain.model.authmethod.AuthenticationMethod;
import com.airlock.iam.common.api.domain.model.event.AuthenticationMethodChanged;
import com.airlock.iam.common.api.domain.model.event.ContextDataChanged;
import com.airlock.iam.common.api.domain.model.event.CrontoDeviceDeleted;
import com.airlock.iam.common.api.domain.model.event.DeviceTokenDeleted;
import com.airlock.iam.common.api.domain.model.event.DeviceTokenRegistered;
import com.airlock.iam.common.api.domain.model.event.EmailAddressAdded;
import com.airlock.iam.common.api.domain.model.event.EmailAddressChanged;
import com.airlock.iam.common.api.domain.model.event.EmailAddressDeleted;
import com.airlock.iam.common.api.domain.model.event.MtanTokenDeleted;
import com.airlock.iam.common.api.domain.model.event.MtanTokenPhoneNumberChanged;
import com.airlock.iam.common.api.domain.model.event.MtanTokenRegistered;
import com.airlock.iam.common.api.domain.model.event.UserCreated;
import com.airlock.iam.common.api.domain.model.event.UserDeleted;
import com.airlock.iam.common.api.domain.model.event.UserLocked;
import com.airlock.iam.common.api.domain.model.event.UserRolesChanged;
import com.airlock.iam.common.api.domain.model.event.UserUnlocked;
import com.airlock.iam.common.domain.model.role.RolesUtil;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

public final class CommonEventValues {
   public static final Function<CrontoDeviceDeleted, Map<String, Object>> CRONTO_DEVICE_DELETED_VALUES = event -> Map.of(
      "event.data.crontoDeviceId", event.deviceId().getInternalId()
   );
   public static final Function<DeviceTokenRegistered, Map<String, Object>> DEVICE_TOKEN_REGISTERED_VALUES = event -> Map.of(
      "event.data.deviceTokenId", event.deviceTokenId().id()
   );
   public static final Function<DeviceTokenDeleted, Map<String, Object>> DEVICE_TOKEN_DELETED_VALUES = event -> Map.of(
      "event.data.deviceTokenId", event.deviceTokenId().id()
   );
   public static final Function<EmailAddressChanged, Map<String, Object>> EMAIL_ADDRESS_CHANGED_VALUES = event -> Map.of(
      "event.data.oldEmailAddress", event.oldEmailAddress().value(), "event.data.newEmailAddress", event.newEmailAddress().value()
   );
   public static final Function<EmailAddressAdded, Map<String, Object>> EMAIL_ADDRESS_ADDED_VALUES = event -> Map.of(
      "event.data.newEmailAddress", event.newEmailAddress().value()
   );
   public static final Function<EmailAddressDeleted, Map<String, Object>> EMAIL_ADDRESS_DELETED_VALUES = event -> Map.of(
      "event.data.oldEmailAddress", event.oldEmailAddress().value()
   );
   public static final Function<UserRolesChanged, Map<String, Object>> USER_ROLES_CHANGED_VALUES = event -> Map.of(
      "event.data.oldRoles",
      RolesUtil.rolesToStringList(event.oldRoles()),
      "event.data.newRoles",
      RolesUtil.rolesToStringList(event.newRoles()),
      "event.data.addedRoles",
      RolesUtil.rolesToStringList(event.addedRoles()),
      "event.data.removedRoles",
      RolesUtil.rolesToStringList(event.removedRoles())
   );
   public static final Function<MtanTokenRegistered, Map<String, Object>> MTAN_TOKEN_REGISTERED_VALUES = event -> Map.of(
      "event.data.mtanNumberId", event.mtanNumberId().getId(), "event.data.mtanNewPhoneNumber", event.newPhoneNumber().getValue()
   );
   public static final Function<MtanTokenDeleted, Map<String, Object>> MTAN_TOKEN_DELETED_VALUES = event -> Map.of(
      "event.data.mtanNumberId", event.mtanNumberId().getId(), "event.data.mtanOldPhoneNumber", event.oldPhoneNumber().getValue()
   );
   public static final Function<MtanTokenPhoneNumberChanged, Map<String, Object>> MTAN_NUMBER_CHANGED_VALUES = event -> Map.of(
      "event.data.mtanNumberId",
      event.mtanNumberId().getId(),
      "event.data.mtanOldPhoneNumber",
      event.oldPhoneNumber().getValue(),
      "event.data.mtanNewPhoneNumber",
      event.newPhoneNumber().getValue()
   );
   public static final Function<ContextDataChanged, Map<String, Object>> CONTEXT_DATA_CHANGED_VALUES = event -> {
      Map<String, Object> result = new HashMap<>();

      for (ContextDataChanged.ContextDataChange change : event.changes()) {
         if (change.oldValue() != null) {
            result.put(String.format("event.data.contextDataChanged.%s.oldValue", change.name()), change.oldValue());
         }

         if (change.newValue() != null) {
            result.put(String.format("event.data.contextDataChanged.%s.newValue", change.name()), change.newValue());
         }
      }

      return Collections.unmodifiableMap(result);
   };
   public static final Function<UserLocked, Map<String, Object>> USER_LOCKED_VALUES = event -> Map.of(
      "event.data.lockReason", event.lockReason().getResourceKey()
   );
   public static final Function<UserUnlocked, Map<String, Object>> USER_UNLOCKED_VALUES = event -> Collections.emptyMap();
   public static final Function<UserCreated, Map<String, Object>> USER_CREATED_VALUES = event -> Collections.emptyMap();
   public static final Function<UserDeleted, Map<String, Object>> USER_DELETED_VALUES = event -> Collections.emptyMap();
   public static final Function<AuthenticationMethodChanged, Map<String, Object>> AUTHENTICATION_METHOD_CHANGED_VALUES = event -> {
      Map<String, String> result = new HashMap<>();
      result.put("event.data.activeAuthenticationMethod", event.activeAuthenticationMethod().map(AuthenticationMethod::getId).orElse(null));
      result.put("event.data.previousAuthenticationMethod", event.previousAuthenticationMethod().map(AuthenticationMethod::getId).orElse(null));
      return Collections.unmodifiableMap(result);
   };

   private CommonEventValues() {
   }
}
