/* BDF - Copyright (c) 2025 Vincent Calame - Exemole
 * Logiciel libre donné sous triple licence :
 * 1) selon les termes de la CeCILL V2
 * 2) selon les termes de l’EUPL V.1.1
 * 3) selon les termes de la GNU GPLv3
 * Voir le fichier licences.txt
 */


package fr.exemole.bdfserver.servlets;

import fr.exemole.bdfserver.multi.subscribe.SubscribeManager;
import fr.exemole.bdfserver.multi.subscribe.SubscribeToken;
import fr.exemole.bdfserver.tools.instruction.BdfErrors;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import net.mapeadores.util.email.EmailUtils;
import net.mapeadores.util.localisation.MessageLocalisation;
import net.mapeadores.util.logging.CommandMessage;
import net.mapeadores.util.logging.ErrorMessageException;
import net.mapeadores.util.logging.LogUtils;
import net.mapeadores.util.models.EmailCore;
import net.mapeadores.util.models.PersonCore;
import net.mapeadores.util.smtp.SmtpParameters;
import net.mapeadores.util.text.StringUtils;


/**
 *
 * @author Vincent Calame
 */
class SubscribeManagerImpl implements SubscribeManager {

    private final SmtpParameters smtpParameters;
    private final Map<String, SubscribeToken> tokenMap = new HashMap<String, SubscribeToken>();

    SubscribeManagerImpl(SmtpParameters smtpParameters) {
        this.smtpParameters = smtpParameters;
    }

    @Override
    public boolean isActive() {
        return true;
    }

    @Override
    public CommandMessage sendToken(PersonCore person, EmailCore email, MessageLocalisation messageLocalisation, String multiRootUrl) throws ErrorMessageException {
        EmailCore fromEmail = smtpParameters.getEmail(SubscribeManager.EMAIL_FROM);
        EmailCore replyEmail = smtpParameters.getEmail(SubscribeManager.EMAIL_REPLYTO);
        EmailCore bccEmail = smtpParameters.getEmail(SubscribeManager.EMAIL_BCC);
        SubscribeToken subscribeToken = createToken(person, email);
        String url = multiRootUrl + "multi-subscribe?token=" + subscribeToken.getToken();
        Session session = EmailUtils.createSession(smtpParameters);
        MimeMessage mimeMessage = new MimeMessage(session);
        MimeMultipart messageContent = new MimeMultipart();
        try {
            mimeMessage.setFrom(EmailUtils.convert(fromEmail));
            mimeMessage.setRecipient(Message.RecipientType.TO, EmailUtils.convert(email));
            if (replyEmail != null) {
                Address[] addresses = new Address[1];
                addresses[0] = EmailUtils.convert(replyEmail);
                mimeMessage.setReplyTo(addresses);
            }
            if (bccEmail != null) {
                mimeMessage.setRecipient(Message.RecipientType.BCC, EmailUtils.convert(bccEmail));
            }
            mimeMessage.setSubject(messageLocalisation.toString("_ title.subscribe.email"), "utf-8");
            MimeBodyPart part = new MimeBodyPart();
            part.setText(getTokenContent(messageLocalisation, person, url));
            messageContent.addBodyPart(part);
            mimeMessage.setContent(messageContent);
            Transport.send(mimeMessage);
        } catch (MessagingException e) {
            throw BdfErrors.error("_ error.exception.sendreport_error", e.getMessage());
        }
        return LogUtils.done("_ done.subscribe.sendtoken", fromEmail.getAddrSpec(), email.getAddrSpec());
    }

    @Override
    public SubscribeToken getSubcribeToken(String token) {
        clearTokens();
        return tokenMap.get(token);
    }

    private String getTokenContent(MessageLocalisation messageLocalisation, PersonCore person, String url) {
        StringBuilder buf = new StringBuilder();
        buf.append(messageLocalisation.toString("_ info.subscribe.email_hello", person.toStandardStyle()));
        buf.append("\n\n");
        buf.append(messageLocalisation.toString("_ info.subscribe.email_intro", person.toStandardStyle()));
        buf.append("\n\n");
        buf.append(url);
        buf.append("\n\n");
        buf.append(messageLocalisation.toString("_ info.subscribe.email_warning", person.toStandardStyle()));
        return buf.toString();
    }

    private SubscribeToken createToken(PersonCore person, EmailCore email) {
        String token = StringUtils.getRandomToken(33);
        if (tokenMap.containsKey(token)) {
            return createToken(person, email);
        }
        SubscribeToken subscribeToken = new SubscribeToken(token, person, email);
        tokenMap.put(token, subscribeToken);
        return subscribeToken;
    }

    private void clearTokens() {
        List<SubscribeToken> list = new ArrayList<SubscribeToken>(tokenMap.values());
        for (SubscribeToken token : list) {
            if (token.isRemoveable()) {
                tokenMap.remove(token.getToken());
            }
        }
    }

}
