package com.airlock.iam.login.app.infrastructure.event;

import com.airlock.iam.airlock2fa.api.domain.model.Airlock2FADeviceActivated;
import com.airlock.iam.airlock2fa.api.domain.model.Airlock2FADeviceDeleted;
import com.airlock.iam.airlock2fa.api.domain.model.Airlock2FADeviceInCooldownUsed;
import com.airlock.iam.authentication.api.domain.model.event.AuthenticationFlowSuccessfullyCompleted;
import com.airlock.iam.common.api.domain.model.authmethod.AuthenticationMethod;
import com.airlock.iam.common.api.domain.model.event.CrontoDeviceActivated;
import com.airlock.iam.common.api.domain.model.event.LoginFromNewDeviceEvent;
import com.airlock.iam.common.api.domain.model.event.PasswordChanged;
import com.airlock.iam.fido.api.domain.model.event.FidoCredentialDeleted;
import com.airlock.iam.fido.api.domain.model.event.FidoCredentialRegistered;
import com.airlock.iam.oauth2.api.domain.model.OAuth2Scope;
import com.airlock.iam.oauth2.api.domain.model.event.OAuth2UserConsentEvent;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public final class LoginappEventValues {
   public static final Function<AuthenticationFlowSuccessfullyCompleted, Map<String, Object>> AUTHENTICATION_SUCCESSFUL_VALUES = event -> Map.of(
      "event.data.authenticationMethods", event.authenticationMethods().stream().map(AuthenticationMethod::getId).collect(Collectors.joining(", ", "[", "]"))
   );
   public static final Function<LoginFromNewDeviceEvent, Map<String, Object>> LOGIN_FROM_NEW_DEVICE_VALUES = event -> Map.of(
      "event.data.browser",
      event.browser(),
      "event.data.operatingSystem",
      event.operatingSystem(),
      "event.data.device",
      event.device(),
      "event.data.countryCode",
      event.countryCode(),
      "event.data.city",
      event.city()
   );
   public static final Function<PasswordChanged, Map<String, Object>> PASSWORD_CHANGED_VALUES = event -> Collections.emptyMap();
   public static final Function<Airlock2FADeviceActivated, Map<String, Object>> AIRLOCK_2FA_DEVICE_ACTIVATED_VALUES = event -> Map.of(
      "event.data.airlock2FAAccountId", event.accountId().getId(), "event.data.airlock2FADeviceId", event.deviceId().getId()
   );
   public static final Function<Airlock2FADeviceDeleted, Map<String, Object>> AIRLOCK_2FA_DEVICE_DELETED_VALUES = event -> Map.of(
      "event.data.airlock2FAAccountId", event.accountId().getId(), "event.data.airlock2FADeviceId", event.deviceId().getId()
   );
   public static final Function<Airlock2FADeviceInCooldownUsed, Map<String, Object>> AIRLOCK_2FA_DEVICE_IN_COOLDOWN_USED_VALUES = event -> Map.of(
      "event.data.airlock2FAAccountId", event.accountId().getId(), "event.data.airlock2FADeviceId", event.deviceId().getId()
   );
   public static final Function<CrontoDeviceActivated, Map<String, Object>> CRONTO_DEVICE_ACTIVATED_VALUES = event -> Map.of(
      "event.data.crontoDeviceId", event.deviceId().getInternalId()
   );
   public static final Function<FidoCredentialDeleted, Map<String, Object>> FIDO_CREDENTIAL_DELETED_VALUES = event -> Map.of(
      "event.data.fidoCredentialId", event.credentialId().asString()
   );
   public static final Function<FidoCredentialRegistered, Map<String, Object>> FIDO_CREDENTIAL_REGISTERED_VALUES = event -> Map.of(
      "event.data.fidoCredentialId",
      event.credentialId().asString(),
      "event.data.fidoPublicKeyCredentialId",
      event.publicKeyCredentialId().base64Url(),
      "event.data.fidoRelyingPartyId",
      event.relyingPartyId().getId()
   );
   public static final Function<OAuth2UserConsentEvent, Map<String, Object>> OAUTH2_USER_CONSENT_VALUES = event -> Map.of(
      "event.data.oauth2.authorizationServerId",
      event.authorizationServerId().id(),
      "event.data.oauth2.clientId",
      event.clientId().id(),
      "event.data.oauth2.acceptedScopes",
      collectionToSortedStringList(event.acceptedScopes(), OAuth2Scope::name),
      "event.data.oauth2.deniedScopes",
      collectionToSortedStringList(event.deniedScopes(), OAuth2Scope::name),
      "event.data.oauth2.alwaysGrantedScopes",
      collectionToSortedStringList(event.alwaysGrantedScopes(), OAuth2Scope::name)
   );

   private LoginappEventValues() {
   }

   private static <S> List<String> collectionToSortedStringList(Collection<S> collection, Function<S, String> toString) {
      return collection.stream().map(toString).sorted().toList();
   }
}
