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

import com.airlock.iam.base.api.domain.model.exception.ViolationException;
import com.airlock.iam.common.api.domain.model.phonenumber.PhoneNumber;
import com.airlock.iam.common.domain.model.sms.Sms;
import com.airlock.iam.common.domain.model.sms.SmsOriginator;
import com.airlock.iam.common.domain.service.sms.SmsSendingService;
import com.airlock.iam.common.domain.service.sms.SmsService;
import com.airlock.iam.core.domain.model.phone.CountryCallingCode;
import com.airlock.iam.core.misc.util.phone.PhoneUtils;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.text.ParseException;
import lombok.NonNull;

public final class SmsSendingServiceImpl implements SmsSendingService {
   private static final ELogger LOG = ELoggerFactory.getLogger(SmsSendingServiceImpl.class);
   @NonNull
   private final SmsService smsService;
   private final boolean flashMessageEnabled;
   @NonNull
   private final CountryCallingCode defaultCountryCode;

   @Override
   public void sendSms(SmsOriginator originator, PhoneNumber number, String message) {
      Sms sms = this.createSmsFor(originator, number, message);
      if (!this.smsService.isValid(sms)) {
         LOG.info(String.format("Not sending any SMS because message %s is invalid", sms));
      } else {
         this.smsService.send(sms);
      }
   }

   public Sms createSmsFor(SmsOriginator originator, PhoneNumber number, String message) {
      String normalizedPhoneNumber = this.normalizedPhoneNumber(number.getValue());
      return Sms.builder().originator(originator.getValue()).phoneNumber(normalizedPhoneNumber).message(message).flashMessage(this.flashMessageEnabled).build();
   }

   private String normalizedPhoneNumber(String phoneNumber) {
      try {
         return PhoneUtils.normalizePhoneNumber(phoneNumber, this.defaultCountryCode.getCode());
      } catch (ParseException e) {
         throw new ViolationException("Could not normalize mobile phone number", e);
      }
   }

   @SuppressFBWarnings(justification = "generated code")
   SmsSendingServiceImpl(@NonNull SmsService smsService, boolean flashMessageEnabled, @NonNull CountryCallingCode defaultCountryCode) {
      if (smsService == null) {
         throw new NullPointerException("smsService is marked non-null but is null");
      }

      if (defaultCountryCode == null) {
         throw new NullPointerException("defaultCountryCode is marked non-null but is null");
      }

      this.smsService = smsService;
      this.flashMessageEnabled = flashMessageEnabled;
      this.defaultCountryCode = defaultCountryCode;
   }

   @SuppressFBWarnings(justification = "generated code")
   public static SmsSendingServiceImpl.SmsSendingServiceImplBuilder builder() {
      return new SmsSendingServiceImpl.SmsSendingServiceImplBuilder();
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class SmsSendingServiceImplBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private SmsService smsService;
      @SuppressFBWarnings(justification = "generated code")
      private boolean flashMessageEnabled;
      @SuppressFBWarnings(justification = "generated code")
      private CountryCallingCode defaultCountryCode;

      @SuppressFBWarnings(justification = "generated code")
      SmsSendingServiceImplBuilder() {
      }

      @SuppressFBWarnings(justification = "generated code")
      public SmsSendingServiceImpl.SmsSendingServiceImplBuilder smsService(@NonNull SmsService smsService) {
         if (smsService == null) {
            throw new NullPointerException("smsService is marked non-null but is null");
         }

         this.smsService = smsService;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public SmsSendingServiceImpl.SmsSendingServiceImplBuilder flashMessageEnabled(boolean flashMessageEnabled) {
         this.flashMessageEnabled = flashMessageEnabled;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public SmsSendingServiceImpl.SmsSendingServiceImplBuilder defaultCountryCode(@NonNull CountryCallingCode defaultCountryCode) {
         if (defaultCountryCode == null) {
            throw new NullPointerException("defaultCountryCode is marked non-null but is null");
         }

         this.defaultCountryCode = defaultCountryCode;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public SmsSendingServiceImpl build() {
         return new SmsSendingServiceImpl(this.smsService, this.flashMessageEnabled, this.defaultCountryCode);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "SmsSendingServiceImpl.SmsSendingServiceImplBuilder(smsService="
            + this.smsService
            + ", flashMessageEnabled="
            + this.flashMessageEnabled
            + ", defaultCountryCode="
            + this.defaultCountryCode
            + ")";
      }
   }
}
