package eu.eudat.logic.managers;

import com.fasterxml.jackson.databind.ObjectMapper;
import eu.eudat.data.entities.Notification;
import eu.eudat.data.entities.UserInfo;
import eu.eudat.data.enumeration.notification.ActiveStatus;
import eu.eudat.data.enumeration.notification.NotifyState;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.logic.services.utilities.MailService;
import eu.eudat.models.data.mail.SimpleMail;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import javax.mail.MessagingException;
import javax.transaction.Transactional;
import java.io.IOException;
import java.util.*;

@Component
public class NotificationManager {
	private static final Logger logger = LoggerFactory.getLogger(NotificationManager.class);

	private ApiContext apiContext;
	private Environment environment;
	private MailService mailService;

	@Autowired
	public NotificationManager(ApiContext apiContext, Environment environment, MailService mailService) {
		this.apiContext = apiContext;
		this.environment = environment;
		this.mailService = mailService;
	}

	@Transactional
	public void sendNotification(Notification notification) throws Exception {
		if (notification.getNotifyState() == NotifyState.ERROR) {
			if (notification.getRetryCount() == null) {
				notification.setRetryCount(0);
			}
			notification.setRetryCount(notification.getRetryCount() + 1);
			if (notification.getRetryCount() >= this.environment.getProperty("notification.maxRetries", Integer.class)) {
				notification.setIsActive(ActiveStatus.INACTIVE);
				notification.setUpdatedAt(new Date());
				return;
			}
		}
		notification.setNotifyState(NotifyState.PROCESSING);
		notification.setNotifiedAt(new Date());
		notification.setUpdatedAt(new Date());
		try {
			Map<String, String> data = new ObjectMapper().readValue(notification.getData(), HashMap.class);
			UserInfo userInfo = this.apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(UUID.fromString(data.get("userId")));
			String subjectTemplate = "";
			String contentTemplate = "";

			switch (notification.getType()) {
				case DMP_MODIFIED:
				case DATASET_MODIFIED:
					subjectTemplate = this.environment.getProperty("notification.modified.subject");
					contentTemplate = mailService.getMailTemplateContent("classpath:templates/notifications/modifiedNotification.html");
					break;
				case DMP_PUBLISH:
					subjectTemplate = this.environment.getProperty("notification.publish.subject");
					contentTemplate = mailService.getMailTemplateContent("classpath:templates/notifications/publishNotification.html");
					break;
				case DMP_FINALISED:
					subjectTemplate = this.environment.getProperty("notification.finalised.subject");
					contentTemplate = mailService.getMailTemplateContent("classpath:templates/notifications/finalisedNotification.html");
					break;
				case DMP_MODIFIED_FINALISED:
				case DATASET_MODIFIED_FINALISED:
					subjectTemplate = this.environment.getProperty("notification.modifiedFinalised.subject");
					contentTemplate = mailService.getMailTemplateContent("classpath:templates/notifications/modifiedFinalisedNotification.html");
					break;
			}


			switch (notification.getContactTypeHint()) {
				case EMAIL:
					this.sendEmailNotification(notification, userInfo, data, subjectTemplate, contentTemplate);
					break;
			}
		}catch (Exception e) {
			notification.setNotifyState(NotifyState.ERROR);
			notification.setUpdatedAt(new Date());
			logger.error(e.getMessage(), e);
		}
	}

	private void sendEmailNotification(Notification notification, UserInfo userInfo, Map<String, String> data, String subjectTemplate, String contentTemplate) throws IOException {
			SimpleMail simpleMail = new SimpleMail();
			simpleMail.setFrom(this.environment.getProperty("mail.from"));
			simpleMail.setSubject(makeSubject(data, subjectTemplate));
			simpleMail.setTo(notification.getContactHint());
			simpleMail.setContent(makeContent(data, notification, userInfo, contentTemplate));
			try {
				mailService.sendSimpleMail(simpleMail);
				notification.setNotifyState(NotifyState.SUCCEEDED);
				notification.setUpdatedAt(new Date());
			} catch (MessagingException e) {
				notification.setNotifyState(NotifyState.ERROR);
				notification.setUpdatedAt(new Date());
				logger.error(e.getMessage(), e);
			}
	}

	private String makeSubject(Map<String, String> data, String subjectTemplate) {
		return subjectTemplate.replace("{name}", data.get("name"));
	}

	private String makeContent(Map<String, String> data, Notification notification, UserInfo userInfo, String template) {
		String content = template;
		content = content.replace("{recipient}", userInfo.getName());
		for (String key : data.keySet()) {
			content = content.replace("{" + key +"}", data.get(key));
		}
		content = content.replace("{host}", this.environment.getProperty("dmp.domain"));
		content = content.replace("{reasonName}", notification.getUserId().getName());
		return content;
	}
}
