package com.dgtly.wxportal.service.impl;

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

import com.dgtly.common.utils.DateUtils;
import com.dgtly.system.domain.Mail;
import com.dgtly.system.domain.OrderTucEarlyWarning;
import com.dgtly.system.domain.SysDictData;
import com.dgtly.system.mapper.OrderTucEarlyWarningMapper;
import com.dgtly.system.mapper.SysBatchSignForMapper;
import com.dgtly.system.mapper.SysUserMapper;
import com.dgtly.system.service.ISysConfigService;
import com.dgtly.system.service.ISysDictDataService;
import com.dgtly.system.util.MailUtils;
import com.dgtly.wxportal.utils.qywxutils.QyWxSendMessageUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.dgtly.wxportal.mapper.WxSendMessageMapper;
import com.dgtly.wxportal.domain.WxSendMessage;
import com.dgtly.wxportal.service.IWxSendMessageService;
import com.dgtly.common.core.text.Convert;

import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.MimeMessage;

/**
 * 企业微信发送消息历史记录Service业务层处理
 * 
 * @author qxp
 * @date 2020-09-02
 */
@Service
public class WxSendMessageServiceImpl implements IWxSendMessageService
{
    @Autowired
    private WxSendMessageMapper wxSendMessageMapper;
    @Autowired
    private QyWxSendMessageUtil qyWxSendMessageUtil;
    @Autowired
    private SysUserMapper userMapper;
    @Autowired
    private ISysConfigService configService;
    @Autowired
    private SysBatchSignForMapper batchSignForMapper;
    @Autowired
    private ISysDictDataService sysDictDataService;
    @Autowired
    private OrderTucEarlyWarningMapper tucEarlyWarningMapper;
    @Autowired
    private MailUtils mailUtils;
    @Value(value = "${spring.mail.username}")
    private String myEmailAccount;
    @Value(value = "${spring.mail.password}")
    public  String myEmailPassword;
    @Value(value = "${spring.mail.host}")
    public  String myEmailSMTPHost;

    /**
     * 查询企业微信发送消息历史记录
     * 
     * @param id 企业微信发送消息历史记录ID
     * @return 企业微信发送消息历史记录
     */
    @Override
    public WxSendMessage selectWxSendMessageById(Long id)
    {
        return wxSendMessageMapper.selectWxSendMessageById(id);
    }

    /**
     * 查询企业微信发送消息历史记录列表
     * 
     * @param wxSendMessage 企业微信发送消息历史记录
     * @return 企业微信发送消息历史记录
     */
    @Override
    public List<WxSendMessage> selectWxSendMessageList(WxSendMessage wxSendMessage)
    {
        return wxSendMessageMapper.selectWxSendMessageList(wxSendMessage);
    }

    /**
     * 新增企业微信发送消息历史记录
     * 
     * @param wxSendMessage 企业微信发送消息历史记录
     * @return 结果
     */
    @Override
    public int insertWxSendMessage(WxSendMessage wxSendMessage)
    {
        wxSendMessage.setCreateTime(DateUtils.getNowDate());
        return wxSendMessageMapper.insertWxSendMessage(wxSendMessage);
    }

    /**
     * 修改企业微信发送消息历史记录
     * 
     * @param wxSendMessage 企业微信发送消息历史记录
     * @return 结果
     */
    @Override
    public int updateWxSendMessage(WxSendMessage wxSendMessage)
    {
        wxSendMessage.setUpdateTime(DateUtils.getNowDate());
        return wxSendMessageMapper.updateWxSendMessage(wxSendMessage);
    }

    /**
     * 删除企业微信发送消息历史记录对象
     * 
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteWxSendMessageByIds(String ids)
    {
        return wxSendMessageMapper.deleteWxSendMessageByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除企业微信发送消息历史记录信息
     * 
     * @param id 企业微信发送消息历史记录ID
     * @return 结果
     */
    @Override
    public int deleteWxSendMessageById(Long id)
    {
        return wxSendMessageMapper.deleteWxSendMessageById(id);
    }

    /**
     * @description: 自提未提货企微消息通知
     * @param:
     * @return:
     * @author: njs
     * @date: 2023/5/15 11:27
     */
    @Override
    public  void sendWxTmsMessage() {
        Map<String, Map<String, Object>> tmsMap =  batchSignForMapper.selectDeliverySelf();
        if(tmsMap !=null && tmsMap.size()>0){
            //自提提货通知
            String temple = configService.selectConfigByKey("wx.notification.self.factory");
            for (String customerId:tmsMap.keySet()
                 ) {
                String user =null;
                String deliverNumber =null;
                String customerName = userMapper.getCustomNameByCode(customerId);
                Map<String, Map<String,Object>> maps = userMapper.selectLoginNamesByOrgCodeSelf(customerId);
                Iterator<Map.Entry<String, Object>> iterator = tmsMap.get(customerId).entrySet().iterator();
                while (iterator.hasNext()){
                    Map.Entry<String, Object> next = iterator.next();
                    if(next.getKey().equals("deliveryNumber")){
                       if(deliverNumber !=null){
                           deliverNumber = deliverNumber+","+next.getValue().toString();
                       }else{
                           deliverNumber=next.getValue().toString();
                       }
                    }
                }
                String empName=userMapper.selectLoginNameByCustomerCode(customerId);
                if(empName !=null){
                    if(maps !=null && maps.size()>0 && maps.get(customerId).get("touser").toString() !=null){
                        user=maps.get(customerId).get("touser").toString()+"|"+empName;
                    }else{
                        user=empName;
                    }

                }else if(maps !=null && maps.size()>0){
                    user=maps.get(customerId).get("touser").toString();
                }
                String CustomerName=customerName+"("+customerId+")";
                String messageDetail = String.format(temple, CustomerName,deliverNumber);
                //消息
                if(user !=null){
                    qyWxSendMessageUtil.sendMsgSelfToCustomer(user,messageDetail, "48");
                }
            }
        }

    }

    /**
     * @description: 业绩进度指标预警邮件/企微消息通知
     * @param:
     * @return:
     * @author: njs
     * @date: 2024/2/4 9:21
     */
    @Override
    public void sendMailAndWxEarlyTucMessage() {
        int year = Calendar.getInstance().get(Calendar.YEAR);
        int month = Calendar.getInstance().get(Calendar.MONTH) + 1;
        String MonthStr = "";
        if(month < 10){
            MonthStr = "0"+month;
        } else {
            MonthStr = String.valueOf(month);
        }
        String startTime = String.valueOf(year)+"01";
        String endTime =  String.valueOf(year)+ MonthStr;
        List<OrderTucEarlyWarning> tucSales = tucEarlyWarningMapper.selectTucGroupSales(startTime,endTime);
        if(tucSales !=null && tucSales.size()>0){
            OrderTucEarlyWarning warning = new OrderTucEarlyWarning();
            List<OrderTucEarlyWarning> earlyWarnings = tucEarlyWarningMapper.selectOrderTucEarlyWarningList(warning);
            if(earlyWarnings !=null && earlyWarnings.size()>0) {
                //比较指标是否有误
                for (OrderTucEarlyWarning early : tucSales
                ) {
                    OrderTucEarlyWarning earlyWarning = tucEarlyWarningMapper.selectOrderTucEarlyWarning(early.getOrgCode());
                    BigDecimal tucNetValue = new BigDecimal(0);
                    if (StringUtils.isNotBlank(early.getOrgNetValue())) {
                        tucNetValue = new BigDecimal(early.getOrgNetValue());
                        tucNetValue = tucNetValue.setScale(0, BigDecimal.ROUND_HALF_UP);
                    }
                    BigDecimal earlyNetValue = new BigDecimal(0);
                    if (StringUtils.isNotBlank(earlyWarning.getOrgNetValue())) {
                        earlyNetValue = new BigDecimal(earlyWarning.getOrgNetValue());
                        earlyNetValue = earlyNetValue.setScale(0, BigDecimal.ROUND_HALF_UP);
                    }
                    if (tucNetValue.compareTo(earlyNetValue) == -1) {
                        sendQw(tucNetValue,earlyNetValue,1,early.getOrgCode(),early.getOrgName());
                        sendMail(tucNetValue,earlyNetValue,1,early.getOrgCode(),early.getOrgName());
                        tucEarlyWarningMapper.deleteOrderTucEarlyWarning();
                        break;
                    }
                    BigDecimal tucTarget = new BigDecimal(0);
                    if (StringUtils.isNotBlank(early.getOrgTarget())) {
                        tucTarget = new BigDecimal(early.getOrgTarget());
                        tucTarget = tucTarget.setScale(0, BigDecimal.ROUND_HALF_UP);
                    }
                    BigDecimal earlyTarget = new BigDecimal(0);
                    if (StringUtils.isNotBlank(earlyWarning.getOrgTarget())) {
                        earlyTarget = new BigDecimal(earlyWarning.getOrgTarget());
                        earlyTarget = earlyTarget.setScale(0, BigDecimal.ROUND_HALF_UP);
                    }
                    if (tucTarget.compareTo(earlyTarget) == -1) {
                        sendQw(tucTarget,earlyTarget,2,early.getOrgCode(),early.getOrgName());
                        sendMail(tucTarget,earlyTarget,2,early.getOrgCode(),early.getOrgName());
                        tucEarlyWarningMapper.deleteOrderTucEarlyWarning();
                        break;
                    }
                    early.setUpdateTime(DateUtils.getNowDate());
                    tucEarlyWarningMapper.updateOrderTucEarlyWarning(early);

                }
            }else{
                tucEarlyWarningMapper.batchInsert(tucSales);
            }
        }
    }

    /**
     * @description: 交货冻结取消要货企微消息通知
     *               取消后按经销商分组，向经销商侧负责人/要货人 + 对应销售推送通知。
     *               消息内容：
     *               "因经销商交货冻结，已取消以下订单的要货，如需重新要货，请解冻后再操作：[订单号列表]"
     * @param canceledOrderList 已取消的要货记录详情列表（含 customerCode/orderNumber/confirmBy）
     */
    @Override
    public void sendFreezeCustomerCancelOrderMessage(List<Map<String, Object>> canceledOrderList) {
        if (canceledOrderList == null || canceledOrderList.isEmpty()) {
            return;
        }
        // 按经销商编码分组，收集订单号和要货人
        Map<String, List<String>> customerOrderMap = new LinkedHashMap<>();
        Map<String, Set<String>> customerConfirmByMap = new LinkedHashMap<>();
        for (Map<String, Object> detail : canceledOrderList) {
            String customerCode = String.valueOf(detail.get("customerCode"));
            String orderNumber  = String.valueOf(detail.get("orderNumber"));
            String confirmBy    = detail.get("confirmBy") != null ? String.valueOf(detail.get("confirmBy")) : "";
            customerOrderMap.computeIfAbsent(customerCode, k -> new ArrayList<>()).add(orderNumber);
            customerConfirmByMap.computeIfAbsent(customerCode, k -> new LinkedHashSet<>()).add(confirmBy);
        }

        for (Map.Entry<String, List<String>> entry : customerOrderMap.entrySet()) {
            String customerCode  = entry.getKey();
            List<String> orderNumbers = entry.getValue();
            Set<String> confirmBys    = customerConfirmByMap.get(customerCode);

            // 拼装通知内容
            String orderList = String.join("、", orderNumbers);
            String msgContent = "因经销商交货冻结，已取消以下订单的要货，如需重新要货，请解冻后再操作：" + orderList;

            // 收集收件人（用 | 分隔，企微支持多人合并）
            Set<String> toUserSet = new LinkedHashSet<>();

            try {
                // 1. 经销商侧负责人
                Map<String, Map<String, Object>> cusUserMap =
                        userMapper.selectLoginNamesByOrgCodeSelf(customerCode);
                if (cusUserMap != null && cusUserMap.containsKey(customerCode)) {
                    Object touser = cusUserMap.get(customerCode).get("touser");
                    if (touser != null && StringUtils.isNotBlank(touser.toString())) {
                        Arrays.stream(touser.toString().split("\\|"))
                              .filter(StringUtils::isNotBlank)
                              .forEach(toUserSet::add);
                    }
                }

                // 2. 要货人（confirm_by 即 sys_user.login_name）
                for (String confirmBy : confirmBys) {
                    if (StringUtils.isNotBlank(confirmBy)) {
                        toUserSet.add(confirmBy);
                    }
                }

                // 3. 对应销售
                String salesLoginName = userMapper.selectLoginNameByCustomerCode(customerCode);
                if (StringUtils.isNotBlank(salesLoginName)) {
                    Arrays.stream(salesLoginName.split("\\|"))
                          .filter(StringUtils::isNotBlank)
                          .forEach(toUserSet::add);
                }
            } catch (Exception e) {
                // 查询收件人失败不阻断主流程
                org.slf4j.LoggerFactory.getLogger(WxSendMessageServiceImpl.class)
                    .error("【交货冻结取货】查询企微通知收件人失败，经销商编码={}", customerCode, e);
            }

            if (toUserSet.isEmpty()) {
                org.slf4j.LoggerFactory.getLogger(WxSendMessageServiceImpl.class)
                    .warn("【交货冻结取货】经销商 {} 未找到任何企微收件人，跳过通知", customerCode);
                continue;
            }

            // 发送（|分隔多人）
            String toUserStr = String.join("|", toUserSet);
            qyWxSendMessageUtil.sendMsgSelfToCustomer(toUserStr, msgContent, "50");

            org.slf4j.LoggerFactory.getLogger(WxSendMessageServiceImpl.class)
                .info("【交货冻结取货】已向经销商 {} 相关人员 [{}] 发送企微通知，订单：{}",
                        customerCode, toUserStr, orderList);
        }
    }

    public Set<String> getConfigValueSet(String dictType){
        Set<String> res = new HashSet<>();
        List<SysDictData> dictDatas = sysDictDataService.selectSimpleDictDataByType(dictType);
        for(SysDictData d: dictDatas){
            res.add(d.getDictValue());
        }
        return res;
    }

    public String getConfigValueUserAccount(String dictType){
        String res = "";
        List<SysDictData> dictDatas = sysDictDataService.selectSimpleDictDataByType(dictType);
        if(dictDatas !=null && dictDatas.size()>0){
            for(int i=0;i<dictDatas.size();i++){
                if(i == 0){
                    res = dictDatas.get(0).getDictValue();
                }else{
                    res = res+"|"+dictDatas.get(i).getDictValue();
                }
            }
        }
        return res;
    }

    void sendQw(BigDecimal tucValue,BigDecimal oldValue,int type,String orgCode,String orgName){
        String sendQwUser = getConfigValueUserAccount("sendQwEarlyWarning");
        if(sendQwUser !=null && !("").equals(sendQwUser) ){
            if(type == 1 ){
                String messageDetail="数据源业绩指标预警：原已复核："+oldValue+"  本次已复核："+tucValue+"  已复核累计减少，请排查是否有误，该组织名称："+orgName+"  组织编码："+orgCode;
                qyWxSendMessageUtil.sendMsgSelfToCustomer(sendQwUser,messageDetail, "66");
            }
            if(type == 2){
                String messageDetail="数据源业绩指标预警：原预算目标："+oldValue+"  本次预算目标："+tucValue+"   预算目标累计减少，请排查是否有误，该组织名称："+orgName+"  组织编码："+orgCode;
                qyWxSendMessageUtil.sendMsgSelfToCustomer(sendQwUser,messageDetail, "66");
            }
        }
    }

    void sendMail(BigDecimal tucValue,BigDecimal oldValue,int type,String orgCode,String orgName){
        // 1. 创建参数配置, 用于连接邮件服务器的参数配置
        Properties props = new Properties();
        props.setProperty("mail.transport.protocol", "smtp");
        props.setProperty("mail.smtp.host", myEmailSMTPHost);
        props.setProperty("mail.smtp.port", "25");
        props.setProperty("mail.smtp.auth", "true");
        props.setProperty("mail.smtp.starttls.enable", "false");
        props.setProperty("mail.smtp.ssl.enable", "false");
        Set<String> sendEmailUser = getConfigValueSet("sendMailEarlyWarning");
        Session session = Session.getDefaultInstance(props);
        session.setDebug(true);

        for (String email : sendEmailUser) {
            Mail mail = new Mail();
            try {
                mail.setFrom(myEmailAccount);
                mail.setTo(email);
                mail.setSubject("立邦随身邦业绩进度数据源预警");
                mail.setContent(getHtmlUserContextList(tucValue,oldValue,type,orgCode,orgName));
                MimeMessage message = mailUtils.createMimeMessage(session, myEmailAccount, email, mail);
                Transport transport = session.getTransport();
                transport.connect(myEmailAccount, myEmailPassword);
                transport.sendMessage(message, message.getAllRecipients());
                transport.close();
            } catch (NoSuchProviderException e) {
                e.printStackTrace();
            } catch (MessagingException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public String getHtmlUserContextList(BigDecimal tucValue,BigDecimal oldValue,int type,String orgCode,String orgName) {
        String str = "";
        String html ="";
        if(type == 1){
            str += "<tr>" +
                    "   <td>" + tucValue
                    + "   </td><td>" + oldValue
                    + "   </td><td>" + orgCode
                    + "   </td><td>" + orgName
                    + "   </td><td>" + "已复核累计减少，请排查是否有误"
                    + "   </td>" +
                    "</tr>";
             html = "<table border='1'  Cellspacing='0'>" +
                    "    <tr>" +
                    "        <th>本次已复核</th>" +
                    "        <th>上次已复核</th>" +
                     "       <th>组织编码</th>" +
                     "       <th>组织名称</th>" +
                    "        <th>检测结果</th>" +
                    "    </tr>" +
                    str +
                    "</table>";
        }

        if(type == 2){
            str += "<tr>" +
                    "   <td>" + tucValue
                    + "   </td><td>" + oldValue
                    + "   </td><td>" + orgCode
                    + "   </td><td>" + orgName
                    + "   </td><td>" + "预算目标累计减少，请排查是否有误"
                    + "   </td>" +
                    "</tr>";
            html = "<table border='1'  Cellspacing='0'>" +
                    "    <tr>" +
                    "        <th>本次预算目标</th>" +
                    "        <th>上次预算目标</th>" +
                    "       <th>组织编码</th>" +
                    "       <th>组织名称</th>" +
                    "        <th>检测结果</th>" +
                    "    </tr>" +
                    str +
                    "</table>";
        }

        return html;
    }
}
