package com.iformall.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.iformall.common.ErrorCode;
import com.iformall.common.IdWorker;
import com.iformall.common.Result;
import com.iformall.common.ResultData;
import com.iformall.domain.dto.WxCUserBasicInfoFilterListDto;
import com.iformall.domain.po.*;
import com.iformall.domain.po.msg.WxMsg;
import com.iformall.enums.*;
import com.iformall.exception.MallinkException;
import com.iformall.mapper.*;
import com.iformall.mq.MqBaseProducer;
import com.iformall.service.PushLimitService;
import com.iformall.service.WxCUserBasicInfoService;
import com.iformall.service.WxCUserTagsService;
import com.iformall.service.WxMsgService;
import com.iformall.utils.DateUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

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


/**
 * @author gongbiao
 */
@Service
public class WxMsgServiceImpl implements WxMsgService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    WxMsgMapper wxMsgMapper;

    @Autowired
    WxMsgConfigMapper wxMsgConfigMapper;

    @Autowired
    WxCUserTagsService wxCUserTagsService;

    @Autowired
    WxCUserBasicInfoMapper wxCUserBasicInfoMapper;

    @Autowired
    WxMsgCallbackMapper wxMsgCallbackMapper;

    @Autowired
    WxMsgModelMapper wxMsgModelMapper;

    @Autowired
    MqBaseProducer mqBaseProducer;

    @Autowired
    WxCUserBasicInfoService wxCUserBasicInfoService;

    @Autowired
    PushLimitService pushLimitService;

    @Override
    public PageInfo<WxMsg> listAsPage(WxMsg record, Integer pageIndex, Integer pageSize) {
        PageHelper.startPage(pageIndex, pageSize);
        List<WxMsg> templist = wxMsgMapper.findList(record);
        for (WxMsg temp : templist) {

            Map<String, String> params = new HashMap<>();
            params.put("msgId", temp.getId().toString());
            params.put("status", "1");
            int success = wxMsgCallbackMapper.queryMsgSendTotal(params);
            params.put("status", "0");
            int error = wxMsgCallbackMapper.queryMsgSendTotal(params);
            temp.setSuccessNumber(success);
            temp.setErrorNumber(error);
        }

        PageInfo<WxMsg> pageInfo = new PageInfo<>(templist);
        return pageInfo;
    }

    @Override
    public WxMsg getById(Long id) {

        WxMsg wxMsg = wxMsgMapper.selectById(id);
        Map<String, String> params = new HashMap<>();
        params.put("msgId", wxMsg.getId().toString());
        params.put("status", "1");
        int success = wxMsgCallbackMapper.queryMsgSendTotal(params);
        params.put("status", "0");
        int error = wxMsgCallbackMapper.queryMsgSendTotal(params);
        wxMsg.setSuccessNumber(success);
        wxMsg.setErrorNumber(error);

        return wxMsg;
    }

    @Async
    public ResultData saveOrUpdate(WxMsg wxMsg, WxMsgConfig wxMsgConfig) {

        //新增记录
        if (wxMsg.getId() == null) {
            //草稿
            if (wxMsg.getStatus().equals(EnumMsgStatus.MSG_STATUS_DRAFT.getCode())) {
                final IdWorker idWorker = IdWorker.get();
                wxMsg.setId(idWorker.nextId());
                wxMsg.setCreatetime(new Date());
                wxMsgMapper.insert(wxMsg);
                return new ResultData(Result.SUCCESS, "已保存到草稿箱");

            }

            //是否立即发送
            if (wxMsg.getIsright().equals(EnumMsgSend.MSG_SEND_IMMEDIATELY.getCode())) {
                wxMsg.setStatus(EnumMsgStatus.MSG_STATUS_SENDED.getCode());
                if (wxMsg.getExpectSendNumber().intValue() > 1000) {
                    batchSendMsg(wxMsg, wxMsgConfig, null);
                } else {
                    //sendmsg(wxMsg, wxMsgConfig, null);
                    wxMsg.setWxMsgConfig(wxMsgConfig);
                    wxMsg.setCouponInject(null);
                    wxMsg.setMsgType(EnumMsgRecordType.SMS_CALLBACK.getCode());
                    wxMsg.setReceiver(wxMsg.getPhones());
                    mqBaseProducer.sendMessage(wxMsg, EnumMsgMqTopic.DEFAULT.getCode(),EnumMsgMqTag.DEFAULT.getCode(),null);
                }
                return new ResultData(Result.SUCCESS, "短信已发送");
            } else {
                wxMsg.setStatus(EnumMsgStatus.MSG_STATUS_NOT_SEND.getCode());
                final IdWorker idWorker = IdWorker.get();
                long id = idWorker.nextId();
                wxMsg.setId(id);
                wxMsg.setCreatetime(new Date());
                wxMsgMapper.insert(wxMsg);
                return new ResultData(Result.SUCCESS, "短信会在预设时间发送", id);
            }

        } else {
            //草稿
            if (wxMsg.getStatus().equals(EnumMsgStatus.MSG_STATUS_DRAFT.getCode())) {
                wxMsgMapper.updateById(wxMsg);
                return new ResultData(Result.SUCCESS, "已保存到草稿箱");
            }

            //是否立即发送
            if (wxMsg.getIsright().equals(EnumMsgSend.MSG_SEND_IMMEDIATELY.getCode())) {
                wxMsg.setStatus(EnumMsgStatus.MSG_STATUS_SENDED.getCode());
                if (wxMsg.getExpectSendNumber().intValue() > 1000) {
                    batchSendMsg(wxMsg, wxMsgConfig, null);
                } else {
                    //sendmsg(wxMsg, wxMsgConfig, null);
                    wxMsg.setWxMsgConfig(wxMsgConfig);
                    wxMsg.setMsgType(EnumMsgRecordType.SMS_CALLBACK.getCode());
                    wxMsg.setReceiver(wxMsg.getPhones());
                    mqBaseProducer.sendMessage(wxMsg, EnumMsgMqTopic.DEFAULT.getCode(),EnumMsgMqTag.DEFAULT.getCode(),EnumMsgMqKey.DEFAULT.getCode());
                }
                return new ResultData(Result.SUCCESS, "短信已发送");
            } else {
                //定时
                wxMsg.setStatus(EnumMsgStatus.MSG_STATUS_NOT_SEND.getCode());
                wxMsgMapper.updateById(wxMsg);
                return new ResultData(Result.SUCCESS, "短信会在预设时间发送");
            }

        }
    }

    @Override
    public void deleteById(Long id) {
        wxMsgMapper.deleteById(id);
    }

    @Override
    public ResultData add(WxMsg wxMsg){
    //不是草稿检验疲劳度
        if (!wxMsg.getStatus().equals(EnumMsgStatus.MSG_STATUS_DRAFT.getCode())) {
            if (wxMsg.getIsright().equals(EnumMsgSend.MSG_SEND_IMMEDIATELY.getCode())) {
                try {
                    pushLimitService.checkSendTime(wxMsg.getTenantId());
                } catch (MallinkException e) {
                    logger.error(e.getMessage());
                    return new ResultData(e.getErrorCode(), e.getMessage());
                }
            } else {
                PushLimit pushLimit = pushLimitService.getPushLimit(wxMsg.getTenantId());
                if(pushLimit.getEnable().equals(EnumEnableType.Enable.getCode())) {
                    // 1.2 疲劳度时间是否启用
                    if(pushLimit.getTimeEnable().equals(EnumEnableType.Enable.getCode())) {
                        String sendtime = wxMsg.getSendtime();
                        Date date = DateUtils.stringToDate(sendtime, "yyyy-MM-dd HH:mm:ss");
                        boolean isInDate = DateUtils.isInDate(date, pushLimit.getTimeStart(), pushLimit.getTimeEnd());
                        if (!isInDate) {
                            return new ResultData(ErrorCode.PUSH_LIMIT_NOT_INRANG);
                        }
                    }
                }
            }

            if(wxMsg.getId()!=null){
                //如果不是草稿必然之前状态是草稿，删除
                deleteById(wxMsg.getId());
                wxMsg.setId(null);
            }

        }

        //1、手机多条以逗号分隔，直接通过实体得到wxmsg.getphones
        //2、通过标签
        String phones = wxMsg.getPhones();
        List<WxCUserBasicInfoFilterListDto> filter = wxMsg.getFilterList();
        if (!phones.isEmpty() && !filter.isEmpty()) {//两种方式只能选其一
            return new ResultData(ErrorCode.MSG_SEND_WAY_CHOOSE_ERROR);
        }
        if (phones.isEmpty() && filter.isEmpty()) {//两种方式必须选其一
            return new ResultData(ErrorCode.MSG_SEND_WAY_CHOOSE_ERROR);
        }

        if (phones.isEmpty()) {//没有手工输入手机号时解析标签,有，继续流转
            List<WxCUserBasicInfo> list =
                    wxCUserBasicInfoService.listByFilterList(wxMsg.getTenantId(),wxMsg.getFilterList());
            wxMsg.setExpectSendNumber(list.size());//预计发送数量
            phones = list.stream().map(u -> u.getPhone()).collect(Collectors.joining(","));
            if (phones==null || phones.isEmpty()) {//解析之后手机号依然不存在时返回
                return new ResultData(ErrorCode.MSG_NO_VALID_PHONE);
            }
            wxMsg.setPhones(StringUtils.join(phones));
            wxMsg.setTags(JSON.toJSONString(wxMsg.getFilterList()));
        } else {
            String[] phoneSplit = phones.split(",");
            Set<String> phoneSet = new HashSet<>(Arrays.asList(phoneSplit));
            wxMsg.setExpectSendNumber(phoneSet.size());//预计发送数量
            wxMsg.setPhones(StringUtils.join(phoneSet,","));
        }

        //从短信配置中查询密钥 bid 等信息
        WxMsgConfig wxMsgConfig = new WxMsgConfig();
        wxMsgConfig.setTenantId(wxMsg.getTenantId());
        List<WxMsgConfig> wxMsgConfigs = wxMsgConfigMapper.findList(wxMsgConfig);
        if (wxMsgConfigs.size() == 0) return new ResultData(ErrorCode.MSG_SERVER_NOT_FIND, "您还未接入短信运营商，请联系平台管理员");
        wxMsgConfig = wxMsgConfigs.get(0);

        if (wxMsgConfig.getRemains() == 0) {
            logger.info("短信数量为0");
            return new ResultData(ErrorCode.MSG_SUM_ZERO);
        }

        if (wxMsgConfig.getRemains() < wxMsg.getExpectSendNumber()) {
            logger.info("短信数量不足");
            return new ResultData(ErrorCode.MSG_SUM_INSUFFICENT);
        }
        saveOrUpdate(wxMsg, wxMsgConfig);
        return new ResultData();
    }


    @Async
    @Override
    public void sendMsgFromCouponInject(WxMsg wxmsg, WxMsgConfig wxMsgConfig, WxCouponInject couponInject) {
        batchSendMsg(wxmsg, wxMsgConfig, couponInject);
    }


    public void batchSendMsg(WxMsg wxMsg, WxMsgConfig wxMsgConfig, WxCouponInject couponInject) {

        String[] split = wxMsg.getPhones().split(",");
        int length = split.length;
        int extra = length % 1000;
        int extracount = extra > 0 ? (length / 1000 + 1) : (length / 1000);
        int index = extracount - 1;
        for (int i = 0; i < extracount; i++) {
            if (extra > 0 && i == index) {
                List<String> phoneList = Arrays.asList(split).subList(i * 1000, length);
                String phones = StringUtils.join(phoneList, ",");
                wxMsg.setPhones(phones);
                wxMsg.setExpectSendNumber(extra);
                wxMsg.setWxMsgConfig(wxMsgConfig);
                wxMsg.setCouponInject(couponInject);
                wxMsg.setMsgType(EnumMsgRecordType.SMS_CALLBACK.getCode());
                wxMsg.setReceiver(wxMsg.getPhones());
                mqBaseProducer.sendMessage(wxMsg, EnumMsgMqTopic.DEFAULT.getCode(),EnumMsgMqTag.DEFAULT.getCode(),EnumMsgMqKey.DEFAULT.getCode());
            } else {
                List<String> phoneList = Arrays.asList(split).subList(i * 1000, (i + 1) * 1000);
                String phones = StringUtils.join(phoneList, ",");
                wxMsg.setExpectSendNumber(1000);
                wxMsg.setPhones(phones);
                wxMsg.setWxMsgConfig(wxMsgConfig);
                wxMsg.setCouponInject(couponInject);
                wxMsg.setMsgType(EnumMsgRecordType.SMS_CALLBACK.getCode());
                wxMsg.setReceiver(wxMsg.getPhones());
                mqBaseProducer.sendMessage(wxMsg, EnumMsgMqTopic.DEFAULT.getCode(),EnumMsgMqTag.DEFAULT.getCode(),EnumMsgMqKey.DEFAULT.getCode());
            }
        }
    }


    @Override
    public void addMsgCallback(WxMsg wxmsg, String batchNo) {
        logger.info("营销短信发送时主动添加回调记录开始...");
        String phones = wxmsg.getPhones();
        String[] split = phones.split(",");
        final IdWorker idWorker = IdWorker.get();
        for (String phone : split) {
            WxMsgCallback queryMsgCallback = new WxMsgCallback();
            queryMsgCallback.setTenantId(wxmsg.getTenantId());
            queryMsgCallback.setPhone(phone);
            queryMsgCallback.setBatchNo(batchNo);
            Integer count = wxMsgCallbackMapper.selectCount(new QueryWrapper<>(queryMsgCallback));
            if (count > 0) {
                logger.info("营销短信回调主动添加-批次" + batchNo + "手机号" + phone + "已存在");
                continue;
            }
            WxMsgCallback wxMsgCallback = new WxMsgCallback();
            wxMsgCallback.setId(idWorker.nextId());
            wxMsgCallback.setPhone(phone);
            wxMsgCallback.setTenantId(wxmsg.getTenantId());
            wxMsgCallback.setBatchNo(batchNo);
            wxMsgCallback.setMsgId(wxmsg.getId());
            wxMsgCallback.setStatus(EnumMsgSendStatus.MSG_SENDING.getCode());
            wxMsgCallback.setStatusMsg(EnumMsgSendStatus.MSG_SENDING.getMessage());
            wxMsgCallback.setCreatetime(new Date());
            wxMsgCallbackMapper.insert(wxMsgCallback);
        }
        logger.info("营销短信发送时主动添加回调记录结束...");
    }


}
