package cn.exploring.engine.server.core.notify;

import freemarker.template.Template;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import java.io.UnsupportedEncodingException;
import java.util.*;

/**
 * 小程序通知服务类
 */
public class NotifyService {
    private MailSender mailSender;
    private String sendFrom;
    private String sendTo;

    private SmsSender smsSender;
    private List<Map<String, String>> smsTemplate = new ArrayList<>();

    private WxTemplateSender wxTemplateSender;
    private List<Map<String, String>> wxTemplate = new ArrayList<>();

    public boolean isMailEnable() {
        return mailSender != null;
    }

    public boolean isSmsEnable() {
        return smsSender != null;
    }

    public boolean isWxEnable() {
        return wxTemplateSender != null;
    }

    /**
     * 短信消息通知
     *
     * @param phoneNumber 接收通知的电话号码
     * @param message     短消息内容，这里短消息内容必须已经在短信平台审核通过
     */
    @Async
    public void notifySms(String phoneNumber, String message) {
        if (smsSender == null)
            return;

        smsSender.send(phoneNumber, message);
    }

    /**
     * 短信模版消息通知
     *
     * @param phoneNumber 接收通知的电话号码
     * @param notifyType  通知类别，通过该枚举值在配置文件中获取相应的模版ID
     * @param params      通知模版内容里的参数，类似"您的验证码为{1}"中{1}的值
     */
    @Async
    public void notifySmsTemplate(String phoneNumber, NotifyType notifyType, String[] params) {
        if (smsSender == null) {
            return;
        }

        String templateIdStr = getTemplateId(notifyType, smsTemplate);
        if (templateIdStr == null) {
            return;
        }

        int templateId = Integer.parseInt(templateIdStr);
        smsSender.sendWithTemplate(phoneNumber, templateId, params);
    }

    /**
     * 以同步的方式发送短信模版消息通知
     *
     * @param phoneNumber 接收通知的电话号码
     * @param notifyType  通知类别，通过该枚举值在配置文件中获取相应的模版ID
     * @param params      通知模版内容里的参数，类似"您的验证码为{1}"中{1}的值
     * @return
     */
    public SmsResult notifySmsTemplateSync(String phoneNumber, NotifyType notifyType, String[] params) {
        if (smsSender == null)
            return null;

        int templateId = Integer.parseInt(getTemplateId(notifyType, smsTemplate));

        return smsSender.sendWithTemplate(phoneNumber, templateId, params);
    }

    /**
     * 微信模版消息通知,不跳转
     * <p>
     * 该方法会尝试从数据库获取缓存的FormId去发送消息
     *
     * @param touser     接收者openId
     * @param notifyType 通知类别，通过该枚举值在配置文件中获取相应的模版ID
     * @param params     通知模版内容里的参数，类似"您的验证码为{1}"中{1}的值
     */
    @Async
    public void notifyWxTemplate(String touser, NotifyType notifyType, String[] params) {
        if (wxTemplateSender == null)
            return;

        String templateId = getTemplateId(notifyType, wxTemplate);
        wxTemplateSender.sendWechatMsg(touser, templateId, params);
    }

    /**
     * 微信模版消息通知，带跳转
     * <p>
     * 该方法会尝试从数据库获取缓存的FormId去发送消息
     *
     * @param touser     接收者openId
     * @param notifyType 通知类别，通过该枚举值在配置文件中获取相应的模版ID
     * @param params     通知模版内容里的参数，类似"您的验证码为{1}"中{1}的值
     * @param page       点击消息跳转的页面
     */
    @Async
    public void notifyWxTemplate(String touser, NotifyType notifyType, String[] params, String page) {
        if (wxTemplateSender == null)
            return;

        String templateId = getTemplateId(notifyType, wxTemplate);
        wxTemplateSender.sendWechatMsg(touser, templateId, params, page);
    }

    /**
     * 邮件消息通知,
     * 接收者在spring.mail.sendto中指定
     *
     * @param subject 邮件标题
     * @param content 邮件内容
     */
    @Async
    public void notifyMail(String subject, String content) {
        if (mailSender == null)
            return;

        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(sendFrom);
        message.setTo(sendTo);
        message.setSubject(subject);
        message.setText(content);
        mailSender.send(message);
    }

    @Autowired
    private JavaMailSender mailSender1;
    @Async
    public void sendHtmlMail(String to, String subject, String content) throws MessagingException {
        MimeMessage message = mailSender1.createMimeMessage();
        try {
            message.setSubject(MimeUtility.encodeText(content,MimeUtility.mimeCharset("gb2312"), null));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        message.setContent(content, "text/html;charset=gbk"); // 设置邮件格式
        message.setSentDate(new Date()); // 设置邮件发送日期

        //true 表⽰示需要创建⼀一个 multipart message
        MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
        helper.setFrom("engine1314@163.com");
        helper.setTo(to);
        helper.setSubject(subject);
        helper.setText(content, true);

        mailSender1.send(message);
    }

    private MimeMessage initMimeMessage(JavaMailSenderImpl javaMailSender) throws MessagingException {
        System.setProperty("mail.mime.splitlongparameters","false");

        javaMailSender.setHost("smtp.exmail.qq.com");//链接服务器
        javaMailSender.setPort(465);
        javaMailSender.setUsername(MAIL_USERNAME);//账号
        javaMailSender.setPassword(MAIL_PASSWORD);//密码
        javaMailSender.setDefaultEncoding("UTF-8");

        Properties properties = new Properties();
        properties.setProperty("mail.smtp.auth", "true");//开启认证
        //properties.setProperty("mail.debug", "true");//启用调试
        properties.setProperty("mail.smtp.timeout", "10000");//设置链接超时
        properties.setProperty("mail.smtp.port", "465");//设置端口
        properties.setProperty("mail.smtp.socketFactory.port", "465");//设置ssl端口
        properties.setProperty("mail.smtp.socketFactory.fallback", "false");
        properties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        javaMailSender.setJavaMailProperties(properties);

        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        return mimeMessage;
    }

    @Autowired
    private FreeMarkerConfigurer configurer;
    private static final String MAIL_USERNAME = "tzs@xuanzang.com.cn";
    private static final String MAIL_PASSWORD = "Xz@123";

    /**
     * 戈15报名成功邮件通知
     * 1.发AB组类型通知；
     * 2.发志愿者类型通知；
     * 3.发媒体摄影组类型通知
     * 4.合作伙伴组类型通知
     * @param params
     * @param to
     * @param subType
     */
    @Async
    public void sendG15RegistrationSuccessMail1(Object params, String to, int subType) {
        try {
            JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
            MimeMessage mimeMessage = initMimeMessage(javaMailSender);
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8");

            helper.setFrom(MAIL_USERNAME, "戈十五");
            helper.setTo(InternetAddress.parse(to)); //发送给谁
            helper.setSubject("第十五届玄奘之路商学院戈壁挑战赛报名成功"); //邮件标题

            if (subType == 1) {
                /*ClassPathResource file1 = new ClassPathResource("emailAttachment/第十五届玄奘之路商学院戈壁挑战赛章程.pdf");
                ClassPathResource file2 = new ClassPathResource("emailAttachment/第十五届玄奘之路商学院戈壁挑战赛标配装备推荐.xls");
                helper.addAttachment("第十五届玄奘之路商学院戈壁挑战赛章程.pdf", file1);
                helper.addAttachment("第十五届玄奘之路商学院戈壁挑战赛标配装备推荐.xls", file2);*/

                ClassPathResource file1 = new ClassPathResource("emailAttachment/第十五届玄奘之路商学院戈壁挑战赛-A+组赛事章程.pdf");
                helper.addAttachment("第十五届玄奘之路商学院戈壁挑战赛-A+组赛事章程.pdf", file1);

            }

            Map<String, Object> model = new HashMap<>();
            model.put("params", params);

            String templateName = "g15RegistrationSuccess" + subType + ".ftl";
            Template template = configurer.getConfiguration().getTemplate(templateName);
            String text = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
            helper.setText(text, true);
            javaMailSender.send(mimeMessage);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 戈15h5注册邮件验证码
     * @param params
     * @param to
     */
    @Async
    public void sendG15H5AuthCodeMail(Object params, String to) {
        try {
            JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
            MimeMessage mimeMessage = initMimeMessage(javaMailSender);
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8");

            helper.setFrom(MAIL_USERNAME, "戈十五");
            helper.setTo(InternetAddress.parse(to));//发送给谁
            helper.setSubject("第十五届玄奘之路商学院戈壁挑战赛验证码");//邮件标题

            Map<String, Object> model = new HashMap<>();
            model.put("params", params);
            Template template = configurer.getConfiguration().getTemplate("g15H5AuthCode.ftl");
            String text = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
            helper.setText(text, true);
            javaMailSender.send(mimeMessage);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private String getTemplateId(NotifyType notifyType, List<Map<String, String>> values) {
        for (Map<String, String> item : values) {
            String notifyTypeStr = notifyType.getType();

            if (item.get("name").equals(notifyTypeStr))
                return item.get("templateId");
        }
        return null;
    }

    public void setMailSender(MailSender mailSender) {
        this.mailSender = mailSender;
    }

    public void setSendFrom(String sendFrom) {
        this.sendFrom = sendFrom;
    }

    public void setSendTo(String sendTo) {
        this.sendTo = sendTo;
    }

    public void setSmsSender(SmsSender smsSender) {
        this.smsSender = smsSender;
    }

    public void setSmsTemplate(List<Map<String, String>> smsTemplate) {
        this.smsTemplate = smsTemplate;
    }

    public void setWxTemplateSender(WxTemplateSender wxTemplateSender) {
        this.wxTemplateSender = wxTemplateSender;
    }

    public void setWxTemplate(List<Map<String, String>> wxTemplate) {
        this.wxTemplate = wxTemplate;
    }
}
