package com.airlock.iam.common.domain.service.email;

import com.airlock.iam.base.api.domain.model.email.EmailAddress;
import com.airlock.iam.base.api.domain.model.exception.FailureException;
import com.airlock.iam.base.misc.log.LogUtil;
import com.airlock.iam.common.api.domain.service.email.EmailService;
import com.airlock.iam.common.api.domain.service.email.EmailServiceException;
import com.airlock.iam.core.misc.impl.authen.StringResourceProvider;
import com.airlock.iam.core.misc.impl.email.HtmlEscapingUtil;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.mail.internet.AddressException;
import jakarta.mail.internet.InternetAddress;
import java.util.List;
import java.util.Locale;
import java.util.Map;

public final class EmailSenderServiceImpl implements EmailSenderService {
   private static final ELogger LOG = ELoggerFactory.getLogger(EmailSenderServiceImpl.class);
   private final String subjectResourceKey;
   private final String bodyResourceKey;
   private final boolean sendAsHtml;
   private final boolean htmlEscapingEnabled;
   private final EmailService emailService;
   private final StringResourceProvider stringResourceProvider;

   @Override
   public void sendEmail(EmailAddress recipientAddress, Locale language, Map<String, Object> variables) {
      try {
         String subject = this.translate(this.subjectResourceKey, language, variables);
         String body = this.translate(this.bodyResourceKey, language, HtmlEscapingUtil.sanitize(variables, this.sendAsHtml && this.htmlEscapingEnabled));
         this.emailService.sendEmail(List.of(new InternetAddress(recipientAddress.value())), List.of(), List.of(), subject, body, this.sendAsHtml);
      } catch (EmailServiceException e) {
         throw new FailureException("Failed to send channel verification email: " + e.getMessage(), e);
      } catch (AddressException e) {
         LOG.debug("Invalid email address: " + LogUtil.logSafeString(recipientAddress.value()));
         throw new FailureException("Invalid email address.");
      }
   }

   private String translate(String key, Locale language, Map<String, Object> variables) {
      return this.stringResourceProvider
         .translateResourceKey(language, key, variables)
         .orElseThrow(() -> new FailureException("Cannot translate template key: " + key));
   }

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

   @SuppressFBWarnings(justification = "generated code")
   private EmailSenderServiceImpl(
      String subjectResourceKey,
      String bodyResourceKey,
      boolean sendAsHtml,
      boolean htmlEscapingEnabled,
      EmailService emailService,
      StringResourceProvider stringResourceProvider
   ) {
      this.subjectResourceKey = subjectResourceKey;
      this.bodyResourceKey = bodyResourceKey;
      this.sendAsHtml = sendAsHtml;
      this.htmlEscapingEnabled = htmlEscapingEnabled;
      this.emailService = emailService;
      this.stringResourceProvider = stringResourceProvider;
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class EmailSenderServiceImplBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private String subjectResourceKey;
      @SuppressFBWarnings(justification = "generated code")
      private String bodyResourceKey;
      @SuppressFBWarnings(justification = "generated code")
      private boolean sendAsHtml;
      @SuppressFBWarnings(justification = "generated code")
      private boolean htmlEscapingEnabled;
      @SuppressFBWarnings(justification = "generated code")
      private EmailService emailService;
      @SuppressFBWarnings(justification = "generated code")
      private StringResourceProvider stringResourceProvider;

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

      @SuppressFBWarnings(justification = "generated code")
      public EmailSenderServiceImpl.EmailSenderServiceImplBuilder subjectResourceKey(String subjectResourceKey) {
         this.subjectResourceKey = subjectResourceKey;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailSenderServiceImpl.EmailSenderServiceImplBuilder bodyResourceKey(String bodyResourceKey) {
         this.bodyResourceKey = bodyResourceKey;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailSenderServiceImpl.EmailSenderServiceImplBuilder sendAsHtml(boolean sendAsHtml) {
         this.sendAsHtml = sendAsHtml;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailSenderServiceImpl.EmailSenderServiceImplBuilder htmlEscapingEnabled(boolean htmlEscapingEnabled) {
         this.htmlEscapingEnabled = htmlEscapingEnabled;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailSenderServiceImpl.EmailSenderServiceImplBuilder emailService(EmailService emailService) {
         this.emailService = emailService;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailSenderServiceImpl.EmailSenderServiceImplBuilder stringResourceProvider(StringResourceProvider stringResourceProvider) {
         this.stringResourceProvider = stringResourceProvider;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailSenderServiceImpl build() {
         return new EmailSenderServiceImpl(
            this.subjectResourceKey, this.bodyResourceKey, this.sendAsHtml, this.htmlEscapingEnabled, this.emailService, this.stringResourceProvider
         );
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "EmailSenderServiceImpl.EmailSenderServiceImplBuilder(subjectResourceKey="
            + this.subjectResourceKey
            + ", bodyResourceKey="
            + this.bodyResourceKey
            + ", sendAsHtml="
            + this.sendAsHtml
            + ", htmlEscapingEnabled="
            + this.htmlEscapingEnabled
            + ", emailService="
            + this.emailService
            + ", stringResourceProvider="
            + this.stringResourceProvider
            + ")";
      }
   }
}
