package org.jeecg.modules.adweb.enquiry.service.impl;

import cn.hutool.core.collection.CollUtil;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;

import jakarta.annotation.Resource;

import lombok.Data;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.DictModel;
import org.jeecg.common.util.FastJsonUtil;
import org.jeecg.modules.adweb.common.service.FeishuService;
import org.jeecg.modules.adweb.common.util.AdwebRedisUtil;
import org.jeecg.modules.adweb.common.util.JedisUtil;
import org.jeecg.modules.adweb.enquiry.constant.EnquiryConstants;
import org.jeecg.modules.adweb.enquiry.constant.EnquirySendStatus;
import org.jeecg.modules.adweb.enquiry.entity.AdwebEnquiry;
import org.jeecg.modules.adweb.enquiry.entity.AdwebEnquiryForm;
import org.jeecg.modules.adweb.enquiry.entity.EnquiryEmailMessage;
import org.jeecg.modules.adweb.enquiry.mapper.EnquiryEmailMessageMapper;
import org.jeecg.modules.adweb.enquiry.service.IAdwebEnquiryFormService;
import org.jeecg.modules.adweb.enquiry.service.IEnquiryEmailMessageService;
import org.jeecg.modules.adweb.site.entity.AdwebSite;
import org.jeecg.modules.adweb.site.service.IAdwebSiteService;
import org.jeecg.modules.adweb.system.entity.SysException;
import org.jeecg.modules.adweb.system.service.IMasterSubAccountRelationService;
import org.jeecg.modules.adweb.system.service.ISysExceptionService;
import org.jeecg.modules.message.handle.enums.SendMsgTypeEnum;
import org.jeecg.modules.message.handle.impl.EmailSendMsgHandle;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.service.ISysDictService;
import org.jeecg.modules.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: adweb_enquiry_email_message
 * @Author: jeecg-boot
 * @Date: 2023-02-01
 * @Version: V1.0
 */
@Service
public class EnquiryEmailMessageServiceImpl extends ServiceImpl<EnquiryEmailMessageMapper, EnquiryEmailMessage> implements IEnquiryEmailMessageService {

    private static byte[] redisKey = EnquiryConstants.ENQUIRY_EMAIL.getBytes();

    @Resource
    private EnquiryEmailMessageMapper enquiryEmailMessageMapper;

    @Resource
    private FeishuService feishuService;

    @Resource
    private AdwebRedisUtil adwebRedisUtil;

    @Resource
    private ISysDictService sysDictService;

    @Resource
    private IAdwebEnquiryFormService adwebEnquiryFormService;

    @Resource
    private ISysExceptionService sysExceptionService;

    @Resource
    private IAdwebSiteService adwebSiteService;

    @Resource
    @Lazy
    private ISysUserService sysUserService;

    @Autowired
    private IMasterSubAccountRelationService masterSubAccountRelationService;

    @Override
    public void sendEnquiryEmail(Long enquiryId) {
        String keyName = "ENQUIRY_SEND_EMAIL_" + enquiryId;
        if (!adwebRedisUtil.lock(keyName, 10 * 60 * 1000)) {
            return;
        }

        QueryWrapper<EnquiryEmailMessage> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("enquiry_id", enquiryId);
        queryWrapper.eq("send_status", EnquirySendStatus.WAIT_SEND);
        List<EnquiryEmailMessage> messageList = list(queryWrapper);
        if (CollUtil.isNotEmpty(messageList)) {
            UpdateWrapper<EnquiryEmailMessage> updateWrapper = new UpdateWrapper<>();
            updateWrapper.in("id", messageList.stream().map(EnquiryEmailMessage::getId).collect(Collectors.toList()));
            updateWrapper.set("send_status", EnquirySendStatus.SENDING);
            updateWrapper.set("send_start_time", new Date());
            this.update(updateWrapper);
            for (EnquiryEmailMessage message : messageList) {
                sendEmailByMessage(message);
            }
        }

        adwebRedisUtil.unlock(keyName);
    }

    @Override
    public void sendEmailByMessage(EnquiryEmailMessage message) {
        try {
            EmailSendMsgHandle sendMsgHandle = (EmailSendMsgHandle) Class.forName(SendMsgTypeEnum.EMAIL.getImplClass()).newInstance();
            AdwebSite site = adwebSiteService.getOne(new QueryWrapper<AdwebSite>().eq("code", message.getSiteCode()));
            String fromName = Objects.toString(site.getCompanyName(), site.getName());
            sendMsgHandle.sendMsg(message.getEmail(), fromName, getEmailContent(message.getEnquiryId()));
            dealSendSuccess(message);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            dealSendFail(message, e.getMessage());
        }
    }

    /**
     * 处理发送时间超过10分钟的邮件消息
     * 1、清除发送时间
     *
     * @return 如果返回true，需要重新发送
     */
    // private boolean dealTimeoutMessage(EnquiryEmailMessage message) {
    //     Date now = new Date();
    //     Date dealTime = message.getSendStartTime();
    //     if (DateUtil.between(dealTime, now, DateUnit.MINUTE) >= 10) {
    //         message.setSendStartTime(new Date());
    //         updateById(message);
    //         return true;
    //     }
    //     return false;
    // }

    /**
     * 邮件发送失败处理
     * 1、更新发送状态
     * 2、清除发送时间
     */
    private void dealSendSuccess(EnquiryEmailMessage message) {
        message.setSendStatus(EnquirySendStatus.SEND_SUCCESS);
        message.setSendStartTime(null);
        updateById(message);
    }

    /**
     * 邮件发送失败处理
     * 1、增加错误次数
     * 2、更新发送状态
     * 3、清除发送时间
     * 4、如果错误次数到达三次，发送飞书通知
     */
    private void dealSendFail(EnquiryEmailMessage message, String errorMsg) {
        if (StringUtils.isEmpty(errorMsg)) {
            errorMsg = "发送询盘邮件失败";
        }
        message.setSendErrorNum(message.getSendErrorNum() + 1);
        if (message.getSendErrorNum() >= 3) {
            message.setSendStatus(EnquirySendStatus.SEND_FAIL);
        } else {
            message.setSendStatus(EnquirySendStatus.WAIT_SEND);
        }
        message.setSendStartTime(null);
        String msg = Objects.toString(message.getSendErrorMsg(), "");
        msg = msg + "," + errorMsg;
        message.setSendErrorMsg(msg);
        updateById(message);
        if (message.getSendErrorNum() >= 3) {
            feishuService.sendEnquiryEmailFailMsg(message.getEnquiryId(), message.getSiteCode(), message.getEmail(), errorMsg);
        }

        // 异常入库
        SysException exception = new SysException();
        exception.setType(0);
        exception.setFunctionModule("发送询盘邮件错误");
        exception.setExceptionDetail(errorMsg);
        exception.setCreateTime(new Date());
        exception.setStatus(1);
        exception.setHandle(0);
        exception.setPriority(1);
        sysExceptionService.save(exception);
    }

    private String getEmailContent(long enquiryId) {
        List<DictModel> dictModels = sysDictService.queryDictItemsByCode("enquiry_email_template");
        String head = "", item = "", tail = "";
        for (DictModel dictModel : dictModels) {
            if ("head".equals(dictModel.getText())) {
                head = dictModel.getValue();
            }
            if ("item".equals(dictModel.getText())) {
                item = dictModel.getValue();
            }
            if ("tail".equals(dictModel.getText())) {
                tail = dictModel.getValue();
            }
        }

        StringBuilder content = new StringBuilder();
        content.append(head);

        AdwebEnquiryForm adwebEnquiryForm = adwebEnquiryFormService.getByEnquiryId(enquiryId);

        List<EnquiryFormItem> formItems = new ArrayList<>();
        //wpforms
        if("wpforms".equals(adwebEnquiryForm.getPluginName())){
            formItems = dealWpformEnquiryForm(adwebEnquiryForm);
        }else{
            formItems = dealElementerEnquiryForm(adwebEnquiryForm);
        }

        for (int i = 0; i < formItems.size(); i++) {
            EnquiryFormItem enquiryFormItem = formItems.get(i);
            String formItemName = enquiryFormItem.getName();
            String formItemValue = enquiryFormItem.getValue();
            String item1 = new String(item);
            item1 = item1.replace("{{title}}", formItemName);
            item1 = item1.replace("{{content}}", formItemValue == null || formItemValue == "" ? " " : formItemValue);
            if (i == 0) {
                item1 = item1.replace("border-top:1px solid #dddddd;", "");
            }
            content.append(item1);
        }
        content.append(tail);
        return content.toString();
    }

    /**
     * 获取待发送询盘
     * 1、首次发送失败的
     * 2、超过timeout分钟未处理的
     *
     * @param timeout 留给首次实时处理的时间，单位分钟，超过这个时间则认为首次邮件发送失败，应该由定时器处理
     * @param num     获取邮件数量
     * @return 邮件列表
     */
    @Override
    public List<EnquiryEmailMessage> getWaitSendEmail(int timeout, int num) {
        return enquiryEmailMessageMapper.getWaitSendEmail(timeout, num);
    }

    /**
     * 添加并发送询盘邮件
     * @param adwebEnquiry
     */
    @Override
    public Result<?> addAndEnquiryEmailMsg(AdwebEnquiry adwebEnquiry, String uid){
        //处理已有发送的询盘邮件
        List<String> emailList = new ArrayList<>();
        if("ALL".equals(uid)){
            //获取子账户邮箱
            List<String> subAccountIdList = masterSubAccountRelationService.getSubAccountIdByMaster(String.valueOf(adwebEnquiry.getUid()));
            if (!subAccountIdList.isEmpty()) {
                List<SysUser> principalEmailList = sysUserService.list(new QueryWrapper<SysUser>().in("id", subAccountIdList).eq("del_flag", 0).isNotNull("email").ne("email","").select("id", "email"));
                if (CollectionUtils.isNotEmpty(principalEmailList)) {
                    emailList = principalEmailList.stream().map(SysUser::getEmail).collect(Collectors.toList());
                }
            }
        }else{
            SysUser sysUser = sysUserService.getById(adwebEnquiry.getPrincipalUid());
            if(StringUtils.isNotBlank(sysUser.getEmail())){
                emailList.add(sysUser.getEmail());
            }
        }

        if(CollectionUtils.isNotEmpty(emailList)){
            QueryWrapper<EnquiryEmailMessage> enquiryEmailMessageQueryWrapper = new QueryWrapper<>();
            enquiryEmailMessageQueryWrapper.eq("enquiry_id", adwebEnquiry.getId());
            enquiryEmailMessageQueryWrapper.eq("site_code", adwebEnquiry.getSiteCode());
            enquiryEmailMessageQueryWrapper.in("email",emailList);
            List<EnquiryEmailMessage> enquiryEmailMessageList = list(enquiryEmailMessageQueryWrapper);

            if(CollectionUtils.isNotEmpty(enquiryEmailMessageList)){
                List<String> oldEmailList = enquiryEmailMessageList.stream().map(EnquiryEmailMessage::getEmail).collect(Collectors.toList());
                List<String> noNeedEmailList = new ArrayList<>();
                for(String email : emailList){
                    if(oldEmailList.contains(email)){
                        noNeedEmailList.add(email);
                    }
                }
                if(CollectionUtils.isNotEmpty(noNeedEmailList)){
                    emailList.removeAll(noNeedEmailList);
                }
            }

            if(CollectionUtils.isNotEmpty(emailList)){
                List<EnquiryEmailMessage> enquiryEmailMessageList1 = new ArrayList<>();
                for (String email : emailList){
                    EnquiryEmailMessage enquiryEmailMessage = new EnquiryEmailMessage();
                    enquiryEmailMessage.setEnquiryId(adwebEnquiry.getId());
                    enquiryEmailMessage.setSiteCode(adwebEnquiry.getSiteCode());
                    enquiryEmailMessage.setEmail(email);
                    enquiryEmailMessage.setFromEmail(adwebEnquiry.getFromEmail());
                    enquiryEmailMessage.setSendStatus(EnquirySendStatus.WAIT_SEND);
                    enquiryEmailMessage.setSendErrorNum(0);
                    enquiryEmailMessage.setCreateTime(new Date());
                    enquiryEmailMessageList1.add(enquiryEmailMessage);
                }

                boolean result = saveBatch(enquiryEmailMessageList1);
                if(result){
                    try {
                        ObjectMapper objectMapper = new ObjectMapper();

                        JedisUtil.lpush(redisKey, objectMapper.writeValueAsBytes(adwebEnquiry.getId()));
                        JedisUtil.publishMsg(EnquiryConstants.ENQUIRY_EMAIL_CHANNEL, EnquiryConstants.ENQUIRY_EMAIL);
                        return Result.OK();
                    } catch (Exception e) {
                        log.error("发送失败询盘id:" + adwebEnquiry.getId());
                        log.error("推送发送询盘邮件的消息失败{}", e);
                    }
                }
            }
            return Result.OK();
        }
        return Result.error("子账户邮箱没有配置，询盘邮件发送失败");
    }

    /**
     * 处理询盘发送信息
     * wpform
     */
    private List<EnquiryFormItem> dealWpformEnquiryForm(AdwebEnquiryForm adwebEnquiryForm){
        String form = adwebEnquiryForm.getForm();
        Map<String, JSONObject> formObj = FastJsonUtil.parseObject(form, Map.class);
        List<EnquiryFormItem> formItems = new ArrayList<>();
        boolean countryFlag = true;
        for (String key : formObj.keySet()) {
            JSONObject formItem = formObj.get(key);
            EnquiryFormItem enquiryFormItem = new EnquiryFormItem();
            enquiryFormItem.setSort(Integer.parseInt(key));
            if("Country".equals(formItem.getString("name")) || "country".equals(formItem.getString("name"))){
                countryFlag = false;
            }
            enquiryFormItem.setName(formItem.getString("name"));
            enquiryFormItem.setValue(formItem.getString("value"));
            formItems.add(enquiryFormItem);
        }
        if(countryFlag) {
            EnquiryFormItem countryForm = new EnquiryFormItem();
            countryForm.setSort(99);
            countryForm.setName("Country");
            countryForm.setValue(adwebEnquiryForm.getCountry());
            formItems.add(countryForm);
        }

        formItems.sort(Comparator.comparingInt(EnquiryFormItem::getSort));
        return formItems;
    }

    /**
     * 处理询盘发送信息
     * elementer
     */
    private List<EnquiryFormItem> dealElementerEnquiryForm(AdwebEnquiryForm adwebEnquiryForm){
        String form = adwebEnquiryForm.getForm();
        Map<String, String> formMap = FastJsonUtil.parseObject(form, Map.class);
        List<EnquiryFormItem> formItems = new ArrayList<>();
        for (String key : formMap.keySet()) {
            String value = formMap.get(key);
            EnquiryFormItem enquiryFormItem = new EnquiryFormItem();
            if(key.contains("phone") || key.contains("Phone")){
                enquiryFormItem.setSort(1);
            }else if (key.contains("email") || key.contains("Email")){
                enquiryFormItem.setSort(2);
            }else if (key.contains("ip") || key.contains("Ip")){
                enquiryFormItem.setSort(3);
            }else if (key.contains("message") || key.contains("Message")){
                enquiryFormItem.setSort(4);
            }else if (key.contains("page") || key.contains("Page")){
                enquiryFormItem.setSort(5);
            }else if (key.contains("name") || key.contains("Name")){
                enquiryFormItem.setSort(6);
            }else if (key.contains("company") || key.contains("Company")){
                enquiryFormItem.setSort(7);
            }else {
                enquiryFormItem.setSort(9);
            }
            enquiryFormItem.setName(key);
            enquiryFormItem.setValue(value);
            formItems.add(enquiryFormItem);
        }

        //国家信息
        EnquiryFormItem countryForm = new EnquiryFormItem();
        countryForm.setSort(8);
        countryForm.setName("Country");
        countryForm.setValue(adwebEnquiryForm.getCountry());
        formItems.add(countryForm);

        formItems.sort(Comparator.comparingInt(EnquiryFormItem::getSort));
        return formItems;
    }
}


@Data
class EnquiryFormItem {

    private int sort;

    private String name;

    private String value;

}
