package com.airlock.iam.common.domain.model.valueprovider;

import com.airlock.iam.base.api.domain.model.exception.ViolationException;
import com.airlock.iam.base.api.domain.model.plugin.LogicForConfig;
import com.airlock.iam.common.api.domain.model.valueprovider.ValueProvider;
import com.airlock.iam.common.application.configuration.valueprovider.DateAndTimeFromStringValueProviderConfig;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.text.ParsePosition;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import org.apache.commons.lang3.time.FastDateFormat;

@LogicForConfig(DateAndTimeFromStringValueProviderConfig.class)
public final class DateAndTimeFromStringValueProvider implements ValueProvider<Date> {
   private static final ELogger LOG = ELoggerFactory.getLogger(DateAndTimeFromStringValueProvider.class);
   private final Provider<ValueProvider<String>> stringDateValueProvider;
   private final Provider<List<FastDateFormat>> formats;

   @Inject
   DateAndTimeFromStringValueProvider(Provider<ValueProvider<String>> stringDateValueProvider, Provider<List<FastDateFormat>> formats) {
      this.stringDateValueProvider = stringDateValueProvider;
      this.formats = formats;
   }

   public Date getValue() {
      String dateAndTimeString = (String)((ValueProvider)this.stringDateValueProvider.get()).getValue();
      if (dateAndTimeString == null) {
         LOG.info("Value is null, returning null instead of a date and time value.");
         return null;
      } else {
         return ((List)this.formats.get())
            .stream()
            .map(fmt -> fmt.parse(dateAndTimeString, new ParsePosition(0)))
            .filter(Objects::nonNull)
            .findFirst()
            .orElseThrow(
               () -> new ViolationException(
                  "Could not parse value '%s' with formats %s"
                     .formatted(dateAndTimeString, ((List)this.formats.get()).stream().map(FastDateFormat::getPattern).toList())
               )
            );
      }
   }
}
