package com.airlock.iam.flow.shared.domain.service.deviveusage;

import com.airlock.iam.base.api.domain.model.user.UserId;
import com.airlock.iam.common.api.domain.model.device.DeviceId;
import com.airlock.iam.common.api.domain.model.device.DeviceType;
import com.airlock.iam.common.api.domain.model.device.usage.AuthenticationDeviceUsage;
import com.airlock.iam.common.domain.model.device.usage.DeviceUsage;
import com.airlock.iam.common.domain.model.device.usage.repository.DeviceUsageRepository;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.Optional;

public class DeviceUsageServiceImpl implements DeviceUsageService {
   private static final ELogger LOG = ELoggerFactory.getLogger(DeviceUsageServiceImpl.class);
   private final Provider<Optional<DeviceUsageRepository>> repository;

   @Inject
   public DeviceUsageServiceImpl(Provider<Optional<DeviceUsageRepository>> repository) {
      this.repository = repository;
   }

   @Override
   public void storeDeviceUsage(UserId userId, AuthenticationDeviceUsage deviceUsageData) {
      Optional<DeviceUsage> deviceUsage = this.retrieveDeviceUsage(userId, deviceUsageData.deviceType(), deviceUsageData.deviceId());
      deviceUsage.ifPresentOrElse(usage -> this.updateDeviceUsage(usage, deviceUsageData), () -> this.insertDeviceUsage(userId, deviceUsageData));
   }

   @Override
   public Optional<DeviceUsage> retrieveDeviceUsage(UserId userId, DeviceType deviceType, DeviceId deviceId) {
      return ((Optional)this.repository.get()).flatMap(repo -> repo.getDeviceUsage(userId, deviceType.id(), deviceId.id()));
   }

   private void updateDeviceUsage(DeviceUsage usage, AuthenticationDeviceUsage deviceUsageData) {
      ((Optional)this.repository.get()).ifPresent(repo -> {
         repo.update(usage.withNewUsage(deviceUsageData.usedAt()));
         LOG.debug("Successfully updated device usage information of device: " + deviceLogString(deviceUsageData));
      });
   }

   private void insertDeviceUsage(UserId userId, AuthenticationDeviceUsage deviceUsageData) {
      ((Optional)this.repository.get()).ifPresent(repo -> {
         repo.insert(DeviceUsage.firstDeviceUsage(userId, deviceUsageData.deviceType().id(), deviceUsageData.deviceId().id(), deviceUsageData.usedAt()));
         LOG.debug("Successfully inserted device usage information of device: " + deviceLogString(deviceUsageData));
      });
   }

   private static String deviceLogString(AuthenticationDeviceUsage deviceUsageData) {
      return String.format(
         "deviceId=%s deviceType=%s lastUsed=%s", deviceUsageData.deviceId().id(), deviceUsageData.deviceType().id(), deviceUsageData.usedAt()
      );
   }
}
