package com.crm.rely.backend.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.crm.rely.backend.core.constant.Constants;
import com.crm.rely.backend.core.entity.custom.info.InfoEntity;
import com.crm.rely.backend.core.entity.system.email.SupplementSendEmailBatchEntity;
import com.crm.rely.backend.core.entity.system.email.SupplementSendEmailEntity;
import com.crm.rely.backend.core.entity.system.email.SysEmailSendEntity;
import com.crm.rely.backend.exception.ServiceException;
import com.crm.rely.backend.service.EmailService;
import com.crm.rely.backend.service.MqSendService;
import com.crm.rely.backend.service.RedisService;
import com.crm.rely.backend.service.SysCountryService;
import com.crm.rely.backend.util.GetIpAndMac;
import com.crm.rely.backend.util.HttpServletRequestUtil;
import com.google.common.base.Strings;
import lombok.extern.log4j.Log4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;

@Log4j
@Service
public class EmailServiceImpl extends BlackListServiceImpl implements EmailService {


    private final static String KEY_PREFIX_CODE = "EMAIL_VALIDATOR_CODE";

    @Autowired
    private MqSendService mqSendService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private SysCountryService sysCountryService;

    public EmailServiceImpl() {
        super("EMAIL_BLACKLIST_", "EMAIL_BLACKLIST_BACK_", 60 * 1000L, 3 * 60 * 1000L, 3, 3, 1);
    }

    /**
     * 发送邮件
     *
     * @param sysEmailSendEntity 发送短信实体
     * @throws ServiceException
     */
    @Override
    public void sendEmail(SysEmailSendEntity sysEmailSendEntity) throws ServiceException {

        sendEmail(sysEmailSendEntity, false, Constants.ACTIVEMQ_JMS_URL_EMAIL);
    }

    @Override
    public void sendEmail(SysEmailSendEntity sysEmailSendEntity, String queueName) throws ServiceException {
        sendEmail(sysEmailSendEntity, false, queueName);
    }

    @Override
    public void sendEmail(List<SysEmailSendEntity> sysEmailSendEntities) throws ServiceException {

        sendEmail(sysEmailSendEntities, false);
    }

    @Override
    public void sendEmail(SysEmailSendEntity sysEmailSendEntity, boolean validate) throws ServiceException {

        sendEmail(sysEmailSendEntity, validate, Constants.ACTIVEMQ_JMS_URL_EMAIL);
    }

    @Override
    public void sendEmail(SysEmailSendEntity sysEmailSendEntity, boolean validate, String queueName) throws ServiceException {
        if (validate) {
            validate(sysEmailSendEntity.getUsers(), sysEmailSendEntity.getEmailSendEnum().getCode(),
                    sysEmailSendEntity.getAddIp());
        } else {
//            removeFromList(sysEmailSendEntity.getUsers(), sysEmailSendEntity.getEmailSendEnum().getCode());
        }

        send(sysEmailSendEntity, queueName);
    }

    @Override
    public void sendEmail(List<SysEmailSendEntity> sysEmailSendEntities, boolean validate) throws ServiceException {
        sendEmail(sysEmailSendEntities, validate, Constants.ACTIVEMQ_JMS_URL_EMAIL);
    }

    @Override
    public void sendEmail(List<SysEmailSendEntity> sysEmailSendEntities, boolean validate, String queueName) throws ServiceException {

        if (validate) {
            for (SysEmailSendEntity sysEmailSendEntity : sysEmailSendEntities) {
                validate(sysEmailSendEntity.getUsers(), sysEmailSendEntity.getEmailSendEnum().getCode(),
                        sysEmailSendEntity.getAddIp());
            }
        }
        send(sysEmailSendEntities, queueName);
    }

    @Override
    public void sendEmailSupplement(Long id) throws ServiceException {

        SupplementSendEmailEntity entity = new SupplementSendEmailEntity();
        entity.setId(id);

        sendEmailSupplement(entity);
    }

    @Override
    public void sendEmailSupplement(List<Long> ids) throws ServiceException {

        for (Long id : ids) {
            sendEmailSupplement(id);
        }
    }

    @Override
    public void sendEmailSupplement(SupplementSendEmailBatchEntity entity) throws ServiceException {

        sendEmailSupplement(entity.getIds());
    }

    @Override
    public void sendEmailSupplement(SupplementSendEmailEntity entity) throws ServiceException {

        String content = JSON.toJSONString(entity, SerializerFeature.WriteMapNullValue);
        mqSendService.send(Constants.ACTIVEMQ_JMS_URL_EMAIL_SUPPLEMENT, content);
    }

    /**
     * 发送邮件验证码并保存到redis 默认过期时间为Constants.SMS_VALIDATECODE_TIME五分钟
     *
     * @param sysEmailSendEntity 发送短信实体
     * @param code               验证码
     * @throws ServiceException
     */
    @Override
    public void sendCode(SysEmailSendEntity sysEmailSendEntity, String code) throws ServiceException {
        //默认过期时间为五分钟
        sendCode(sysEmailSendEntity, code, Constants.EMAIL_VALIDATECODE_TIME * 60 * 1000);
    }

    /**
     * 发送邮件验证码并保存到redis 过期时间为time 毫秒
     *
     * @param sysEmailSendEntity 发送短信实体
     * @param code               验证码
     * @param time               过期时间
     * @throws ServiceException
     */
    @Override
    public void sendCode(SysEmailSendEntity sysEmailSendEntity, String code, long time) throws ServiceException {

        //将所有的邮箱转化为小写
        sysEmailSendEntity.setUsers(sysEmailSendEntity.getUsers().toLowerCase());
        validate(sysEmailSendEntity.getUsers(), sysEmailSendEntity.getEmailSendEnum().getCode(),
                sysEmailSendEntity.getAddIp());

//        String key = KEY_PREFIX_CODE + sysEmailSendEntity.getUsers() + code;
        String key = KEY_PREFIX_CODE + sysEmailSendEntity.getUsers();
        redisService.saveObject(key, code, time);

        send(sysEmailSendEntity);
    }

    /**
     * 验证code
     *
     * @param email
     * @param code
     * @throws ServiceException
     */
    @Override
    public void validateCode(String email, String code) throws ServiceException {

        if (Strings.isNullOrEmpty(email)) {
            throw new ServiceException(Constants.EMAIL_CODE_ERROR);
        }
        email = email.toLowerCase();
//        String key = KEY_PREFIX_CODE + email + code;
        String key = KEY_PREFIX_CODE + email;
        //获取原来的验证码
        String oldCode = redisService.getObject(key);
        //判断验证码是否过期 验证码是否正确
        if (Strings.isNullOrEmpty(oldCode) || Strings.isNullOrEmpty(code) || !oldCode.equals(code)) {
            log.error(String.format("email:%s,code:%s,old code:%s",email,code,oldCode));
            throw new ServiceException(Constants.EMAIL_CODE_ERROR);
        }
        //移除验证码
        redisService.remove(key);
    }

    /**
     * 发送邮件
     *
     * @param sysEmailSendEntity
     * @throws ServiceException
     */
    private void send(SysEmailSendEntity sysEmailSendEntity) throws ServiceException {
        InfoEntity userInfoEntity = getUserInfoEntity();

        //获取ip和地点
        String returnStr = getIpStr();

        send(sysEmailSendEntity, userInfoEntity, returnStr);
    }

    private void send(SysEmailSendEntity sysEmailSendEntity, String queueName) throws ServiceException {
        InfoEntity userInfoEntity = getUserInfoEntity();

        //获取ip和地点
        String returnStr = getIpStr();

        send(sysEmailSendEntity, userInfoEntity, returnStr, queueName);
    }

    private void send(List<SysEmailSendEntity> sysEmailSendEntities) throws ServiceException {

        send(sysEmailSendEntities, Constants.ACTIVEMQ_JMS_URL_EMAIL);
    }

    private void send(List<SysEmailSendEntity> sysEmailSendEntities, String queueName) throws ServiceException {

        InfoEntity userInfoEntity = getUserInfoEntity();

        //获取ip和地点
        String returnStr = getIpStr();

        for (SysEmailSendEntity sysEmailSendEntity : sysEmailSendEntities) {

            send(sysEmailSendEntity, userInfoEntity, returnStr, queueName);
        }
    }

    private void send(SysEmailSendEntity sysEmailSendEntity, InfoEntity userInfoEntity, String returnStr) throws ServiceException {

        send(sysEmailSendEntity, userInfoEntity, returnStr, Constants.ACTIVEMQ_JMS_URL_EMAIL);
    }

    private void send(SysEmailSendEntity sysEmailSendEntity, InfoEntity userInfoEntity, String returnStr,
                      String queueName) throws ServiceException {

        if (Strings.isNullOrEmpty(queueName)) {
            queueName = Constants.ACTIVEMQ_JMS_URL_EMAIL;
        }
        if (userInfoEntity != null) {
            sysEmailSendEntity.setAddUser(userInfoEntity.getId());
        }

        if (!Strings.isNullOrEmpty(returnStr)) {
            sysEmailSendEntity.setAddIp(returnStr);
        }

        sysEmailSendEntity.setAddTime(new Date());

        if (sysEmailSendEntity != null && !Strings.isNullOrEmpty(sysEmailSendEntity.getUsers())) {
            if (sysEmailSendEntity.getBcc() == 1) {
                String content = JSON.toJSONString(sysEmailSendEntity, SerializerFeature.WriteMapNullValue);
                mqSendService.send(queueName, content);
            } else {
                if (sysEmailSendEntity.getSetSent() == 0) {
                    String[] users = sysEmailSendEntity.getUsers().split(",");
                    for (String user : users) {
                        sysEmailSendEntity.setUsers(user);
                        String content = JSON.toJSONString(sysEmailSendEntity, SerializerFeature.WriteMapNullValue);

                        mqSendService.send(queueName, content);
                    }
                } else {

                    String content = JSON.toJSONString(sysEmailSendEntity, SerializerFeature.WriteMapNullValue);

                    mqSendService.send(queueName, content);
                }
            }

        }
    }

    private InfoEntity getUserInfoEntity() throws ServiceException {
        InfoEntity userInfoEntity = null;
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes != null) {
            HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
            if (request != null) {
                userInfoEntity = HttpServletRequestUtil.getLoginInfo(InfoEntity.class, request, redisService, true);
            }
        }
        return userInfoEntity;
    }

    private String getIpStr() throws ServiceException {
        String ipStr = null;
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes != null) {
            HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
            if (request != null) {
                String ip = GetIpAndMac.getIp(request);
                try {
                    ipStr = ip + "-" + sysCountryService.getAdderByIp(ip);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        return ipStr;
    }
}
