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

import com.airlock.iam.common.domain.model.logs.Log;
import com.airlock.iam.common.domain.model.logs.LogSignatureVerification;
import com.airlock.iam.log.usertrail.UserTrailLog;
import java.util.Date;
import org.apache.commons.lang3.StringUtils;

public final class UserTrailLogParserHelper {
   private static final String STATIC_SEQUENCE_NUMBER = "001";
   private static final String MESSAGE_SEPARATOR = " - ";
   private static final String EMPTY_LOG_FIELD = "n/a";

   public static Log mapToLog(UserTrailLog userTrailLog) {
      return Log.builder()
         .timestamp(Date.from(userTrailLog.createdAt()))
         .level(userTrailLog.logLevel())
         .sessionId(userTrailLog.sessionId().orElse("000000000000000000"))
         .requestId(userTrailLog.requestId().orElse("000000000000000000"))
         .sequenceNumber("001")
         .messageLine(formatMessage(userTrailLog))
         .configContextIdentifier(userTrailLog.configurationContext())
         .clientIp((String)userTrailLog.clientIp().orElse(null))
         .signatureVerification(LogSignatureVerification.STATUS_NO_AUDITLOG_ENTRY)
         .build();
   }

   public static UserTrailLog mapToUserTrailLog(Log log) {
      String logMessage = String.join(" ", log.getMessageLines());
      String targetId = parseTargetIdFromLogMessage(logMessage);
      String authenteeProvidedId = parseAuthenteeProvidedIdFromLogMessage(logMessage);
      String nonEmptyConfigurationContext = useDefaultConfigurationContextWhenBlank(log.getConfigContextIdentifier());
      String parsedMessage = parseMessageFromLogMessage(logMessage);
      return UserTrailLog.builder()
         .createdAt(log.getTimestamp().toInstant())
         .logLevel(log.getLevel())
         .targetId(targetId)
         .authenteeId(targetId)
         .authenteeProvidedId(authenteeProvidedId)
         .sessionId(log.getSessionId())
         .requestId(log.getRequestId())
         .configurationContext(nonEmptyConfigurationContext)
         .message(parsedMessage)
         .clientIp(log.getClientIp())
         .build();
   }

   public static boolean hasNonEmptyTargetIdField(UserTrailLog logEntry) {
      return StringUtils.isNotBlank(logEntry.targetId()) && !"n/a".equals(logEntry.targetId());
   }

   private static String formatMessage(UserTrailLog log) {
      return String.format("uid:%s - provided_uid:%s - %s", log.targetId(), log.authenteeProvidedId(), log.message());
   }

   private static String useDefaultConfigurationContextWhenBlank(String configContext) {
      return StringUtils.isBlank(configContext) ? "[DEFAULT]" : configContext;
   }

   private static String parseTargetIdFromLogMessage(String logMessage) {
      String targetId = StringUtils.substringBetween(logMessage, "uid:", " - ");
      return StringUtils.isBlank(targetId) ? "n/a" : targetId;
   }

   private static String parseAuthenteeProvidedIdFromLogMessage(String logMessage) {
      String authenteeProvidedId = StringUtils.substringBetween(logMessage, "provided_uid:", " - ");
      return StringUtils.isBlank(authenteeProvidedId) ? "n/a" : authenteeProvidedId;
   }

   private static String parseMessageFromLogMessage(String logMessage) {
      String[] messageParts = StringUtils.split(logMessage, " - ", 3);
      String message = messageParts.length == 3 ? messageParts[2].trim() : logMessage;
      return StringUtils.isBlank(message) ? "n/a" : message;
   }

   private UserTrailLogParserHelper() {
      throw new AssertionError();
   }
}
