package eu.dnetlib.organizations.utils;

import javax.annotation.PostConstruct;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import eu.dnetlib.common.exceptions.DnetException;
import eu.dnetlib.common.utils.mail.EmailFactory;
import eu.dnetlib.common.utils.mail.EmailMessage;
import eu.dnetlib.organizations.controller.UserRole;
import eu.dnetlib.organizations.model.SystemConfiguration;
import eu.dnetlib.organizations.model.view.UserView;
import eu.dnetlib.organizations.repository.SystemConfigurationRepository;

@Component
public class MailDispatcher {

	@Autowired
	private SystemConfigurationRepository systemConfigurationRepository;

	private final EmailFactory emailFactory = new EmailFactory();

	private boolean enabled = true;

	private String fromMail;
	private String fromName;
	private String toMailAdmin;

	private String newUserMessage;
	private String updateUserMessage;

	private static final Log log = LogFactory.getLog(MailDispatcher.class);

	@PostConstruct
	public void configure() {
		final SystemConfiguration conf = systemConfigurationRepository.findById(SystemConfiguration.DEFAULT_ID).get();
		configure(conf);
	}

	public void configure(final SystemConfiguration conf) {
		this.enabled = conf.getSmtpEnabled();
		this.fromMail = conf.getSmtpFromMail();
		this.fromName = conf.getSmtpFromName();
		this.toMailAdmin = conf.getSmtpToMailAdmin();
		this.newUserMessage = conf.getSmtpNewUserMessage();
		this.updateUserMessage = conf.getSmtpUpdateUserMessage();

		if (StringUtils.isNotBlank(conf.getSmtpHost())) {
			emailFactory.setSmtpHost(conf.getSmtpHost());
		} else {
			emailFactory.setSmtpHost("localhost");
		}
		if (conf.getSmtpPort() != null) {
			emailFactory.setSmtpPort(conf.getSmtpPort());
		} else {
			emailFactory.setSmtpPort(587);
		}
		if (StringUtils.isNotBlank(conf.getSmtpUser())) {
			emailFactory.setSmtpUser(conf.getSmtpUser());
			emailFactory.setSmtpPassword(conf.getSmtpPassword());
		} else {
			emailFactory.setSmtpUser(null);
			emailFactory.setSmtpPassword(null);
		}
	}

	public void sendRequestRegistrationMail(final UserView user) {
		if (StringUtils.isNotBlank(newUserMessage)) {
			final String message = prepareMessage(this.newUserMessage, user);

			for (final String to : StringUtils.split(toMailAdmin, ",")) {
				sendMail("OpenOrgs: new registration request", message, to.trim());
			}
		} else {
			log.warn("Template is empty (newUserMessage)");
		}
	}

	public void sendUpdatedUserMail(final UserView user) {
		if (StringUtils.isNotBlank(updateUserMessage)) {
			final String message = prepareMessage(this.updateUserMessage, user);
			sendMail("OpenOrgs: user updated", message, user.getEmail());
		} else {
			log.warn("Template is empty (updateUserMessage)");
		}
	}

	private String prepareMessage(final String template, final UserView user) {
		final String countries = user.getRole().equals(UserRole.ADMIN.toString()) ? "All" : StringUtils.join(user.getCountries(), ", ");

		return template.replaceAll(":email:", user.getEmail())
			.replaceAll(":fullname:", user.getFullname())
			.replaceAll(":organization:", user.getOrganization())
			.replaceAll(":refperson:", user.getReferencePerson())
			.replaceAll(":reqmessage:", user.getRequestMessage())
			.replaceAll(":role:", user.getRole())
			.replaceAll(":countries:", countries);

	}

	private void sendMail(final String subject, final String content, final String to) {
		if (!enabled) {
			log.debug("Mail not sent: MailDispatcher is disabled");
		} else if (StringUtils.isAnyBlank(subject, content, to, fromMail, fromName)) {
			log.warn("Mail not sent: some fields are empty");
			log.warn("  - subject: " + subject);
			log.warn("  - to: " + to);
			log.warn("  - fromMail: " + fromMail);
			log.warn("  - fromName: " + fromName);
			log.warn("  - content: " + content);
		} else {
			try {
				final EmailMessage mail = emailFactory.prepareEmail(subject, content, fromMail, fromName, to);
				mail.sendMail();
			} catch (final DnetException e) {
				log.error("Error sending mail", e);
			}
		}
	}

}
