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

import com.airlock.iam.authentication.domain.model.event.LoginFromNewDeviceEventFactory;
import com.airlock.iam.authentication.domain.model.event.LoginFromNewDeviceEventImpl;
import com.airlock.iam.base.api.domain.model.event.metadata.EventMetadataItem;
import com.airlock.iam.base.api.domain.model.event.metadata.StandardEventMetadataItemType;
import com.airlock.iam.base.api.domain.model.user.UserId;
import com.airlock.iam.base.domain.model.event.EventCreationData;
import com.airlock.iam.base.domain.model.event.EventPublisher;
import com.airlock.iam.common.api.domain.model.event.LoginFromNewDeviceEvent;
import com.airlock.iam.common.api.domain.model.geolocation.Geolocation;
import com.airlock.iam.common.api.domain.model.request.RequestAttributes;
import com.airlock.iam.flow.shared.domain.model.newdevice.LoginFromNewDeviceUserAgent;
import com.airlock.iam.flow.shared.domain.service.newdevice.LoginFromNewDeviceUserAgentParser;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.Optional;

public final class LoginFromNewDeviceEventFactoryImpl implements LoginFromNewDeviceEventFactory {
   private final Provider<EventCreationData> creationData;
   private final Provider<LoginFromNewDeviceUserAgentParser> userAgentParser;
   private final Provider<EventPublisher> eventPublisher;
   private final Provider<RequestAttributes> requestAttributes;

   @Inject
   public LoginFromNewDeviceEventFactoryImpl(
      Provider<EventCreationData> creationData,
      Provider<LoginFromNewDeviceUserAgentParser> userAgentParser,
      Provider<EventPublisher> eventPublisher,
      Provider<RequestAttributes> requestAttributes
   ) {
      this.creationData = creationData;
      this.userAgentParser = userAgentParser;
      this.eventPublisher = eventPublisher;
      this.requestAttributes = requestAttributes;
   }

   @Override
   public void publishLoggedInFromNewDeviceEvent(UserId userId) {
      Optional<LoginFromNewDeviceUserAgent> userAgent = ((EventCreationData)this.creationData.get())
         .metadata()
         .item(StandardEventMetadataItemType.USER_AGENT_REQUEST_HEADER)
         .map(EventMetadataItem::value)
         .flatMap(((LoginFromNewDeviceUserAgentParser)this.userAgentParser.get())::parse);
      Optional<Geolocation> geolocation = ((RequestAttributes)this.requestAttributes.get()).getGeolocation();
      LoginFromNewDeviceEvent event = new LoginFromNewDeviceEventImpl((EventCreationData)this.creationData.get(), userId, userAgent, geolocation);
      ((EventPublisher)this.eventPublisher.get()).publish(event);
   }
}
