package com.njzscloud.common.email;

import cn.hutool.core.lang.Assert;
import com.njzscloud.common.core.ex.Exceptions;
import com.njzscloud.common.core.tuple.Tuple2;
import com.njzscloud.common.core.utils.Mime;
import lombok.Getter;

import javax.mail.util.ByteArrayDataSource;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * 邮件消息
 */
@Getter
public class MailMessage {
    /**
     * 收件人邮箱
     */
    private final List<String> tos;
    /**
     * 邮件主题
     */
    private final String subject;
    /**
     * 邮件内容
     */
    private final String content;
    /**
     * 是否为 HTML
     */
    private final boolean html;
    /**
     * 附件列表，0-->附件名称、1-->附件内容
     */
    private final List<Tuple2<String, ByteArrayDataSource>> attachmentList;

    /**
     * 创建邮件消息
     *
     * @param tos            收件人邮箱
     * @param subject        邮件主题
     * @param content        邮件内容
     * @param html           是否为 HTML
     * @param attachmentList 附件列表，0-->附件名称、1-->附件内容
     */
    private MailMessage(List<String> tos, String subject, String content, boolean html, List<Tuple2<String, ByteArrayDataSource>> attachmentList) {
        this.tos = tos;
        this.subject = subject;
        this.content = content;
        this.html = html;
        this.attachmentList = attachmentList;
    }

    /**
     * 获取构建器
     *
     * @return 构建器对象
     */
    public static Builder builder() {
        return new Builder();
    }

    /**
     * 构建器
     */
    public static class Builder {
        /**
         * 收件人邮箱
         */
        private List<String> tos;
        /**
         * 邮件主题
         */
        private String subject;
        /**
         * 邮件内容
         */
        private String content;
        /**
         * 是否为 HTML
         */
        private boolean html;
        /**
         * 附件列表，0-->附件名称、1-->附件内容
         */
        private List<Tuple2<String, ByteArrayDataSource>> attachmentList;

        /**
         * 添加收件人邮箱
         *
         * @param to 收件人邮箱
         * @return 构建器对象
         */
        public Builder addTo(String to) {
            if (this.tos == null) {
                this.tos = new ArrayList<>();
            }
            this.tos.add(to);
            return this;
        }

        /**
         * 设置收件人邮箱
         *
         * @param tos 收件人邮箱
         * @return 构建器对象
         */
        public Builder tos(List<String> tos) {
            this.tos = tos;
            return this;
        }

        /**
         * 设置邮件主题
         *
         * @param subject 邮件主题
         * @return 构建器对象
         */
        public Builder subject(String subject) {
            this.subject = subject;
            return this;
        }

        /**
         * 设置邮件内容
         *
         * @param content 邮件内容（常规内容）
         * @return 构建器对象
         */
        public Builder content(String content) {
            this.content = content;
            this.html = false;
            return this;
        }

        /**
         * 设置邮件内容
         *
         * @param content 邮件内容（HTML内容）
         * @return 构建器对象
         */
        public Builder htmlContent(String content) {
            this.content = content;
            this.html = true;
            return this;
        }

        /**
         * 设置附件列表
         *
         * @param attachmentList 附件列表，0-->附件名称、1-->附件内容
         * @return 构建器对象
         */
        public Builder attachmentList(List<Tuple2<String, ByteArrayDataSource>> attachmentList) {
            this.attachmentList = attachmentList;
            return this;
        }

        /**
         * 添加附件
         *
         * @param filename 附件名称
         * @param in       附件
         * @param mime     内容类型
         * @return 构建器对象
         */
        public Builder addAttachment(String filename, InputStream in, String mime) {
            Assert.notBlank(filename, "附件名称不能为空");
            Assert.notNull(in, "附件不能为空");
            Assert.notBlank(mime, "内容类型不能为空");
            if (this.attachmentList == null) {
                this.attachmentList = new ArrayList<>();
            }
            ByteArrayDataSource dataSource;
            try (InputStream is = in) {
                dataSource = new ByteArrayDataSource(is, mime);
            } catch (IOException e) {
                throw Exceptions.error(e, "附件读取失败");
            }
            this.attachmentList.add(Tuple2.create(filename, dataSource));
            return this;
        }

        /**
         * 添加附件
         *
         * @param filename 附件名称
         * @param bytes    附件
         * @param mime     内容类型
         * @return 构建器对象
         */
        public Builder addAttachment(String filename, byte[] bytes, String mime) {
            return addAttachment(filename, new ByteArrayInputStream(bytes), mime);
        }

        /**
         * 添加附件，内容类型默认：application/octet-stream
         *
         * @param filename 附件名称
         * @param bytes    附件
         * @return 构建器对象
         */
        public Builder addAttachment(String filename, byte[] bytes) {
            return addAttachment(filename, new ByteArrayInputStream(bytes), Mime.BINARY);
        }

        /**
         * 添加附件，内容类型默认：application/octet-stream
         *
         * @param filename 附件名称
         * @param in       附件
         * @return 构建器对象
         */
        public Builder addAttachment(String filename, InputStream in) {
            return addAttachment(filename, in, Mime.BINARY);
        }

        /**
         * 构建邮件消息
         *
         * @return MailMessage
         */
        public MailMessage build() {
            Assert.isTrue(this.tos != null && !this.tos.isEmpty(), "收件人邮箱不能为空");
            Assert.notBlank(this.subject, "邮件主题不能为空");
            return new MailMessage(this.tos, this.subject, this.content, this.html, this.attachmentList);
        }
    }
}
