package com.airlock.iam.factor.infrastructure.service.airlock2fa;

import com.airlock.iam.base.api.domain.model.user.UserId;
import com.airlock.iam.base.misc.file.FileName;
import com.airlock.iam.core.misc.util.report.ReportRenderer;
import com.airlock.iam.core.misc.util.report.ReportRendererAgent;
import com.airlock.iam.factor.domain.model.airlock2fa.activation.Airlock2FAActivationLetter;
import com.airlock.iam.factor.domain.model.airlock2fa.qrcode.Airlock2FAQrCodeImage;
import com.airlock.iam.factor.domain.service.airlock2fa.Airlock2FAActivationLetterPrintingService;
import com.airlock.iam.factor.domain.service.airlock2fa.QrCodeImageReader;
import java.nio.file.Path;
import java.sql.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

public class Airlock2FAActivationLetterPrintingServiceImpl implements Airlock2FAActivationLetterPrintingService {
   static final String FILE_NAME_PREFIX = "airlock-2fa-activation";
   private final Airlock2FAActivationLetterPrintingServiceImpl.ContextDataMapProvider contextDataMapProvider;
   private final QrCodeImageReader qrCodeImageReader;
   private final Optional<String> languageAttributeName;
   private final ReportRendererAgent rendererAgent;

   public Airlock2FAActivationLetterPrintingServiceImpl(
      Airlock2FAActivationLetterPrintingServiceImpl.ContextDataMapProvider contextDataMapProvider,
      QrCodeImageReader qrCodeImageReader,
      ReportRenderer renderer,
      Path outputDirectory,
      Optional<Path> workingDirectory,
      Optional<String> languageAttributeName
   ) {
      this(contextDataMapProvider, qrCodeImageReader, languageAttributeName, new ReportRendererAgent(renderer, outputDirectory, workingDirectory));
   }

   Airlock2FAActivationLetterPrintingServiceImpl(
      Airlock2FAActivationLetterPrintingServiceImpl.ContextDataMapProvider contextDataMapProvider,
      QrCodeImageReader qrCodeImageReader,
      Optional<String> languageAttributeName,
      ReportRendererAgent rendererAgent
   ) {
      this.contextDataMapProvider = contextDataMapProvider;
      this.qrCodeImageReader = qrCodeImageReader;
      this.languageAttributeName = languageAttributeName;
      this.rendererAgent = rendererAgent;
   }

   @Override
   public Path printToFile(UserId userId, Airlock2FAActivationLetter activationLetter) {
      Map<String, Object> contextDataMap = this.contextDataMapProvider.get(userId);
      Map<String, Object> parameters = this.parameters(activationLetter, contextDataMap);
      return this.rendererAgent
         .render(
            parameters,
            this.languageAttributeName,
            FileName.builder()
               .prefix("airlock-2fa-activation")
               .delimiterAfterPrefix(true)
               .element(userId.getValue())
               .element(activationLetter.getId().asString())
               .build()
         );
   }

   private Map<String, Object> parameters(Airlock2FAActivationLetter activationLetter, Map<String, Object> contextDataMap) {
      Map<String, Object> parameters = new HashMap<>(contextDataMap);
      Airlock2FAQrCodeImage activationQrCode = this.qrCodeImageReader.retrieveFrom(activationLetter.getEnrollment().getActivationQrCodeUrl().getUrl());
      parameters.put("activationQRCode", activationQrCode.asBufferedImage());
      parameters.put("expires", Date.from(activationLetter.getEnrollment().getExpires()));
      parameters.put("activationCodeShort", activationLetter.getEnrollment().getActivationCodeShort().orElseThrow().getValue());
      return parameters;
   }

   @FunctionalInterface
   public interface ContextDataMapProvider {
      Map<String, Object> get(UserId var1);
   }
}
