package com.dk.mdm.service.mst;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.dk.common.exception.BaseBusinessException;
import com.dk.common.infrastructure.annotaiton.Pagination;
import com.dk.common.infrastructure.constant.Constant;
import com.dk.common.infrastructure.enums.ErrorCodeEnum;
import com.dk.common.infrastructure.xxl.XxlJobUtils;
import com.dk.common.model.pojo.PageList;
import com.dk.common.model.vo.core.StaffEntity;
import com.dk.common.response.ResponseCodeEnum;
import com.dk.common.response.ResponseResultUtil;
import com.dk.common.response.ResponseResultVO;
import com.dk.common.util.HttpUtils;
import com.dk.mdm.feign.UserFeign;
import com.dk.mdm.infrastructure.config.Config;
import com.dk.mdm.infrastructure.convert.mst.CusFollowConvert;
import com.dk.mdm.infrastructure.convert.mst.MeasureReceiptConvert;
import com.dk.mdm.infrastructure.util.AuthUtils;
import com.dk.mdm.mapper.mst.*;
import com.dk.mdm.model.pojo.ivt.InboundItem;
import com.dk.mdm.model.pojo.mst.*;
import com.dk.common.service.BaseService;
import com.dk.common.mapper.BaseMapper;
import com.dk.mdm.model.query.mst.CusFollowQuery;
import com.dk.mdm.model.query.mst.CustomerQuery;
import com.dk.mdm.model.response.mst.CusFollowResponse;
import com.dk.mdm.model.response.mst.CustomerResponse;
import com.dk.common.model.response.mst.StaffResponse;
import com.dk.mdm.model.vo.mst.CusFollowVO;
import com.dk.mdm.model.vo.mst.MeasureReceiptVO;
import com.dk.mdm.service.common.CommonService;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.IntStream;

@Slf4j
@Service
public class CusFollowService extends BaseService<CusFollow> {

    @Override
    public BaseMapper<CusFollow> getRepository() {
        return cusFollowMapper;
    }

    @Autowired
    private CusFollowMapper cusFollowMapper;

    @Autowired
    private CustomerMapper customerMapper;

    @Autowired
    private CustomerService customerService;

    @Autowired
    private CusFollowStaffMapper cusFollowStaffMapper;

    @Autowired
    private CommonService commonService;

    @Autowired
    private CusFollowConvert cusFollowConvert;

    @Autowired
    private StaffMapper staffMapper;


    @Autowired
    private AuthUtils authUtils;

    @Autowired
    private MeasureRoomService measureRoomService;

    @Autowired
    private MeasureReceiptService measureReceiptService;
    @Autowired
    private MeasureReceiptMapper measureReceiptMapper;

    @Autowired
    private MeasureRoomMapper measureRoomMapper;
    @Autowired
    private FollowPlanMapper followPlanMapper;
    @Autowired
    private XxlJobUtils xxlJobUtils;

    @Autowired
    private Config config;

    @Resource
    private UserFeign userFeign;

    @Autowired
    private MeasureReceiptConvert measureReceiptConvert;

    /**
     * @desc : 重写主键
     * @author : 于继渤
     * @date : 2024/2/29 20:29
     */
    @Override
    public String getPrimaryKey() {
        return "follow_id";
    }


    /**
     * @desc : 查询
     * @author : 于继渤
     * @date : 2023/1/5 9:39
     */
    @Pagination
    public ResponseResultVO<PageList<CusFollowResponse>> selectByCond(CusFollowQuery cusFollowQuery) {
        return super.mergeListWithCount(cusFollowQuery, cusFollowMapper.selectByCond(cusFollowQuery),
                cusFollowMapper.countByCond(cusFollowQuery));
    }

    public ResponseResultVO<List<CusFollowResponse>> selectByList(CusFollowQuery cusFollowQuery) {
        return ResponseResultUtil.success(cusFollowMapper.selectByList(cusFollowQuery));
    }

    /**
     * @desc : 跟进id查询
     * @author : 于继渤
     * @date : 2023/1/5 9:39
     */
    public ResponseResultVO<CusFollowResponse> selectById(CusFollowQuery cusFollowQuery) {
        CusFollowResponse cusFollowResponse = cusFollowMapper.selectByCond(cusFollowQuery).get(0);

        if (cusFollowResponse.getFollowId() != null && cusFollowResponse.getMeasureStatus() != null && cusFollowResponse.getMeasureStatus().equals(Constant.BasicDataConstant.MEASURE_STATUS_1.getValue())) {
            //已量尺
            MeasureReceipt measureReceipts = measureReceiptMapper.selectByFollowId(new MeasureReceipt().setFollowId(cusFollowQuery.getFollowId()));
            cusFollowResponse.setMeasureReceipt(measureReceipts);
            //查询 空间
            List<MeasureRoom> measureRooms = measureRoomMapper.selectByReceiptId(new MeasureRoom().setReceiptId(measureReceipts.getReceiptId()));
            cusFollowResponse.setMeasureRoomList(measureRooms);
        }
        return ResponseResultUtil.success(cusFollowResponse);
    }

    /**
     * @desc : 新建
     * @author : 于继渤
     * @date : 2023/1/5 9:39
     */
    @Transactional(
            rollbackFor = {Exception.class}
    )
    public ResponseResultVO<?> insert(CusFollowVO cusFollowVO) {
        CusFollow cusFollow = cusFollowConvert.convertToPo(cusFollowVO);
        //设置ID
        Map<String, Object> uniqueNoteCode = commonService.getUniqueNoteCode(Constant.docNameConstant.CUSTOMERFOLLOW.getName(), true);
        cusFollow.setFollowId(uniqueNoteCode.get("outId").toString());
        //跟进时间
        cusFollow.setFollowTime(LocalDateTime.now());
        //跟进人
        cusFollow.setFollowStaff(authUtils.getStaff().getStaffId());
        //跟进部门
//        cusFollow.setFollowOrg(authUtils.getStaff().getOrgId());
        if (cusFollowVO.getCusId() != null) {
            //查询客户
            Customer customer = customerMapper.selectById(cusFollowVO.getCusId());

            // 查询跟进人是否存在
            CusFollowStaff followStaff = cusFollowStaffMapper.selectByCusFollowStaffId(cusFollowVO.getCusId(), authUtils.getStaff().getStaffId());
            //追加跟进人表
            if (followStaff == null) {
                cusFollowStaffMapper.insert(new CusFollowStaff()
                        .setCusId(cusFollowVO.getCusId())
                        .setFollowStaff(authUtils.getStaff().getStaffId())
                        .setLastFollowId(authUtils.getStaff().getStaffId())
                        .setLastFollowTime(LocalDateTime.now())
                        .setCpId(authUtils.getStaff().getCpId())
                        .setLastFollowStatus(cusFollowVO.getFollowStatus())
                        .setFollowCount(1)
                );
            }
            //追加跟进人
            List<Long> users = new ArrayList<>();
            Object o = customerMapper.selectFollowStaffs(cusFollowVO.getCusId());
            if (o != null && o instanceof Long[]) {
                users = Arrays.asList((Long[]) o);
            }

            if (users == null || users.size() == 0 || (users != null && users.stream().allMatch(Objects::isNull))) {
                users = new ArrayList<>();
            }


            //公海客户跟进后 变成潜客状态
            if (Constant.saleCustomerStatusConstant.SALE_STATUS_INTE.getName().equals(customer.getSaleStatus())) {
                customer.setSaleStatus(Constant.saleCustomerStatusConstant.SALE_STATUS_POTE.getName());
            }
            //已流失客户重新接待后应该变成潜客
            if (Constant.saleCustomerStatusConstant.SALE_STATUS_LOST.getName().equals(customer.getSaleStatus())) {
                customer.setSaleStatus(Constant.saleCustomerStatusConstant.SALE_STATUS_POTE.getName());
            }

            //放入公海客户，清除跟进人
            if (Constant.IntentionConstant.SEA.getValue().equals(cusFollowVO.getIntention())) {
                customer.setFollowStaffs(new ArrayList<>());
                customer.setSaleStatus(Constant.saleCustomerStatusConstant.SALE_STATUS_INTE.getName());
            } else {
                if (!users.contains(authUtils.getStaff().getStaffId())) {
                    List arrList = new ArrayList(users);
                    arrList.add(authUtils.getStaff().getStaffId());
                    customer.setFollowStaffs(arrList);
                }
            }
            //已流失客户，修改状态为流失
            if (Constant.IntentionConstant.LOST.getValue().equals(cusFollowVO.getIntention())) {
                customer.setSaleStatus(Constant.saleCustomerStatusConstant.SALE_STATUS_LOST.getName());
            }

            //如果不是留资接待 修改客户信息
            if (!Constant.BasicDataConstant.FOLLOW_STATUS_4.getValue().equals(cusFollowVO.getFollowStatus())) {
                customer.setCusName(cusFollowVO.getCusName());
                customer.setCusPhone(cusFollowVO.getCusPhone());
                customer.setAddressName(cusFollowVO.getAddressName());
                customer.setAddressNo(cusFollowVO.getAddressNo());
                customer.setAddressGcj02(cusFollowVO.getAddressGcj02());
                customer.setAddressFull(cusFollowVO.getAddressFull());
                customer.setAddressArea(cusFollowVO.getAddressArea());
            }
            customer.setCpId(authUtils.getStaff().getCpId());
            // 同商户 电话不同
            List<CustomerResponse> cusList = customerMapper.selectByCond(
                    new CustomerQuery().setCpId(customer.getCpId()).setCusPhone(customer.getCusPhone()).setFlgValid(true)
            );
//            if (cusList != null && cusList.size() > 0 && cusList.stream().anyMatch(a -> !a.getCusId().equals(customer.getCusId()))) {
//                throw new BaseBusinessException(ErrorCodeEnum.CUSTOMER_SAME_COMPANY_TELEPHONE.getCode(),
//                        ErrorCodeEnum.CUSTOMER_SAME_COMPANY_TELEPHONE.getMessage());
//            }
            customer.setLastFollowId(cusFollow.getFollowId());
            customer.setLastFollowTime(cusFollow.getFollowTime());
            customer.setLastFollowStaff(cusFollow.getFollowStaff());
            //修改跟进次数
            customer.setFollowCount(customer.getFollowCount() + 1);
            customerService.updateByUuid(customer);
        } else if (cusFollowVO.getCusPhone() != null && cusFollowVO.getCusName() != null) {
            //留资接待 新建客户
            Customer customer = new Customer();
            //设置编码
            Map<String, Object> customerNoteCode = commonService.getUniqueNoteCode(Constant.docNameConstant.CUSTOMER.getName(), true);
            customer.setCusId(customerNoteCode.get("outId").toString());
            customer.setCusCode(customerNoteCode.get("outNote").toString());
            //TODO  渠道 取当前登录人员工的渠道 (目前取前台传过来得默认渠道)
            customer.setChannelId(cusFollowVO.getChannelId());
            customer.setCusName(cusFollowVO.getCusName());
            customer.setCusPhone(cusFollowVO.getCusPhone());
            customer.setAddressName(cusFollowVO.getAddressName());
            customer.setAddressNo(cusFollowVO.getAddressNo());
            customer.setAddressGcj02(cusFollowVO.getAddressGcj02());
            customer.setAddressFull(cusFollowVO.getAddressFull());
            customer.setAddressArea(cusFollowVO.getAddressArea());
            customer.setReportStaff(authUtils.getStaff().getStaffId());
            customer.setReportTime(LocalDateTime.now());
            customer.setCpId(authUtils.getStaff().getCpId());
            customer.setStaffId(authUtils.getStaff().getStaffId());
            customer.setOrgId(cusFollowVO.getFollowOrg());
            customer.setFollowCount(1);
            customer.setLastFollowId(cusFollow.getFollowId());
            customer.setLastFollowTime(cusFollow.getFollowTime());
            customer.setLastFollowStaff(cusFollow.getFollowStaff());
            cusFollow.setCusId(customer.getCusId());
            // 同商户 电话不同
            Long count = customerMapper.countByCond(
                    new CustomerQuery().setCpId(customer.getCpId()).setCusPhone(customer.getCusPhone()).setFlgValid(true)
            );
//            if (count > 0) {
//                return ResponseResultUtil.error(ErrorCodeEnum.CUSTOMER_SAME_COMPANY_TELEPHONE.getCode(),
//                        ErrorCodeEnum.CUSTOMER_SAME_COMPANY_TELEPHONE.getMessage());
//            }

            //放入公海客户，清除跟进人
            if (Constant.IntentionConstant.SEA.getValue().equals(cusFollowVO.getIntention())) {
                customer.setFollowStaffs(new ArrayList<>());
                customer.setSaleStatus(Constant.saleCustomerStatusConstant.SALE_STATUS_INTE.getName());
            } else {
                //当前跟进人（业务员）
                customer.setFollowStaffs(new ArrayList<String>() {{
                    add(authUtils.getStaff().getStaffId());
                }});
                customer.setSaleStatus(Constant.saleCustomerStatusConstant.SALE_STATUS_POTE.getName());
            }
            //新建客户或编辑客户
            customerMapper.insert(customer);
        }
        // 约量尺
        if (Constant.BasicDataConstant.FOLLOW_STATUS_3.getValue().equals(cusFollow.getFollowStatus())) {
            // 量尺状态：待量尺
            cusFollow.setMeasureStatus(Constant.BasicDataConstant.MEASURE_STATUS_2.getValue());
        }
        if (cusFollow.getFollowData() == null) {
            cusFollow.setFollowData("无");
        }
        super.insert(cusFollow);
        //设计师
        StaffResponse designStaff = null;
        if (cusFollow.getDesignStaff() != null) {
            designStaff = staffMapper.selectById(cusFollow.getDesignStaff());
        }

        // 只要有跟进日期
        if (cusFollow.getNextFollowTime() != null) {
            // 保存跟进信息
            saveToXxlJob(cusFollow);
        }

        return ResponseResultUtil.success();
    }


    /**
     * @desc : 客户跟进提醒回调
     * @author : 姜永辉
     * @date : 2022-06-29 14:22
     */
    @Transactional(rollbackFor = {Exception.class})
//    @XxlJob("customer-reminder")
    public ResponseResultVO customerReminder() {
        log.info("@XxlJob(\"customer-reminder\")");
        log.info("followPlan id: {}", XxlJobHelper.getJobParam());
//        String planid = "10112024-0715-0000-0000-0004a8b4d1e6";
        FollowPlan followPlan = followPlanMapper.selectById(XxlJobHelper.getJobParam());
        if (followPlan != null) {
            CusFollow follow = cusFollowMapper.selectById(followPlan.getFollowId());
            if (follow != null) {
                FollowPlan plan = new FollowPlan().setPlanId(followPlan.getPlanId());
                try {
                    //发消息
                    String msg = sendFollowMessage(follow, followPlan);
                    if (msg == null) {
                        plan.setCallStatus(Constant.CallStatus.CALL_STATUS_DONE.getName() + "");
                    } else {
                        plan.setCallStatus(Constant.CallStatus.CALL_STATUS_ERROR.getName() + "").setRemarks(msg);
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("客户跟进发送消息异常：{}", e.getMessage());
                    plan.setCallStatus(Constant.CallStatus.CALL_STATUS_ERROR.getName() + "").setRemarks(e.getMessage());
                }

                //修改状态
                followPlanMapper.update(plan,
                        new UpdateWrapper<FollowPlan>().lambda()
                                .eq(FollowPlan::getPlanId, UUID.fromString(plan.getPlanId())));

                //删除任务
                xxlJobUtils.delete(followPlan.getXxlJobId());
            }

        }
        return null;
    }

    /**
     * @desc : 客户计划任务提醒回调
     * @author : jyh
     * @date : 2022-06-29 14:22
     */
    @Transactional(rollbackFor = {Exception.class})
//    @XxlJob("plan-reminder")
    public void planReminder() {
        log.info("@XxlJob(\"plan-reminder\")");
        log.info("followPlan id: {}", XxlJobHelper.getJobParam());
//        String planid = "10112024-0715-0000-0000-0004a8b4d1e6";
        FollowPlan followPlan = followPlanMapper.selectById(XxlJobHelper.getJobParam());
        if (followPlan != null && followPlan.getFlgValid()) {
            FollowPlan plan = new FollowPlan().setPlanId(followPlan.getPlanId());
            try {
                //发消息
                String msg = sendFollowPlanMessage(followPlan);
                if (msg == null) {
                    plan.setCallStatus(Constant.CallStatus.CALL_STATUS_DONE.getName() + "");
                } else {
                    plan.setCallStatus(Constant.CallStatus.CALL_STATUS_ERROR.getName() + "").setRemarks(msg);
                }
            } catch (Exception e) {
                e.printStackTrace();
                log.error("跟进任务发送消息异常：{}", e.getMessage());
                plan.setCallStatus(Constant.CallStatus.CALL_STATUS_ERROR.getName() + "").setRemarks(e.getMessage());
            }
            //修改状态
            followPlanMapper.updateById(plan);
            //删除任务
            xxlJobUtils.delete(followPlan.getXxlJobId());

        }
    }

    /**
     * @desc : 发送跟进消息
     * @author : 姜永辉
     * @date : 2022-05-27 09:34
     */
    public String sendFollowMessage(CusFollow follow, FollowPlan followPlan) {
        log.info("sendFollowMessage:{}", JSONObject.toJSONString(follow));
        // 跟进人
        StaffResponse followStaff = null;
        // 当跟进计划状态为跟尺时 获取设计师信息
        if(follow.getFollowStatus().equals("跟进状态-约尺")){
            followStaff = staffMapper.selectById(follow.getDesignStaff());
        }else {
            followStaff = staffMapper.selectById(followPlan.getFollowUser());
        }
        //查到跟进人
        if (followStaff != null) {
            log.info("sendFollowMessage:{}", JSONObject.toJSONString(followStaff));
            Customer customer = customerMapper.selectById(follow.getCusId());
            if (customer != null) {
                String loginType = "4";
//                List<String> list = new ArrayList<>();
                Map<String, String> keywordMap = new HashMap<>();
                if (Constant.BasicDataConstant.FOLLOW_STATUS_4.getValue().equals(follow.getFollowStatus()) ||
                        Constant.BasicDataConstant.FOLLOW_STATUS_1.getValue().equals(follow.getFollowStatus()) ||
                        Constant.BasicDataConstant.FOLLOW_STATUS_5.getValue().equals(follow.getFollowStatus())) {
//                    list.add("您有客户需要跟进");
                    keywordMap.put("remark", "您有客户需要跟进");
                    loginType = "4";

                } else if (Constant.BasicDataConstant.FOLLOW_STATUS_6.getValue().equals(follow.getFollowStatus())) {
//                    list.add("您有客户需要量尺服务");
                    keywordMap.put("remark", "您有客户需要量尺服务");
                    loginType = "6";

                } else if (Constant.BasicDataConstant.FOLLOW_STATUS_2.getValue().equals(follow.getFollowStatus())) {
//                    list.add("您有客户邀约进店");
                    keywordMap.put("remark", "您有客户邀约进店");
                    loginType = "2";

                } else if (Constant.BasicDataConstant.FOLLOW_STATUS_3.getValue().equals(follow.getFollowStatus())) {
//                    list.add("您有客户需要约尺服务");
                    keywordMap.put("remark", "您有客户需要约尺服务");
                    loginType = "3";
                }
//                list.add(customer.getCusName());
//                list.add(customer.getCusPhone());
                LocalDateTime followTime = follow.getFollowTime();
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

                keywordMap.put("cusName", customer.getCusName());
                keywordMap.put("cusPhone", customer.getCusPhone());
                keywordMap.put("followTime", followTime.format(formatter));
                // 查询跟进人的openid和publicOpenId   7.19 加了userWxId 刘尧
                ResponseResultVO<?> resultVO = userFeign.getUser(followStaff.getWxUserId());
                // 如果没有成功返回，状态设置为待审
                if (resultVO.getCode() != ResponseCodeEnum.SUCCESS.getCode()) {
                    log.error("客户查询异常：为空{}", follow.getCusId());
                    return ResponseCodeEnum.SELECT_NULL.getMessage();
                } else {
                    Map<String, Object> user = (Map<String, Object>) resultVO.getData();
                    if (user != null) {
                        // 发送消息
                        Map<String, Object> mapMessage = new HashMap<>();
                        mapMessage.put("loginType", loginType);
                        mapMessage.put("otherParam", follow);
//                        mapMessage.put("publicOpenId", user.get("publicOpenId"));
                        mapMessage.put("userWxId", user.get("userWxId"));
                        mapMessage.put("first", "客户跟进提醒");
//                      mapMessage.put("keywordList", list);
//                      mapMessage.put("keywordMap", keywordMap);
                        mapMessage.put("remark", "客户跟进备注");
//                      sendUniformMessage(mapMessage);
                        List<String> miniMessageModelIds = config.getMiniMessageModelIds();
                        // 构造对应的显示信息 和模板数据结构对应
                        JSONObject data = new JSONObject();
                        data.put("time4", createDataItem("value", String.valueOf(keywordMap.get("followTime"))));
                        data.put("thing1", createDataItem("value", String.valueOf(keywordMap.get("cusName"))));
                        data.put("phone_number2", createDataItem("value", String.valueOf(keywordMap.get("cusPhone"))));
                        data.put("thing6", createDataItem("value", String.valueOf(keywordMap.get("remark"))));
                        data.put("thing5", createDataItem("value", String.valueOf(mapMessage.get("remark"))));
                        wxMessagePush(miniMessageModelIds.get(0), data, mapMessage);
                    }
                }

                return null;
            } else {
                log.error("客户查询异常：为空{}", follow.getCusId());
                return ResponseCodeEnum.SELECT_NULL.getMessage();
            }
        } else {
            log.error("跟进人异常：为空{}", followPlan.getFollowUser());
            return ResponseCodeEnum.SELECT_NULL.getMessage();
        }

    }

    /**
     * @author : sh4wmoo
     * @date : 2021-7-20 13:49
     * @desc : iBOSS推送公众号消息卡片
     */
    public ResponseResultVO sendUniformMessage(Map<String, Object> map) {
        log.info("推送参数：{}", JSON.toJSONString(map));

        // 3.获取token 231011
        String token = this.getWxPublicAccountToken(); //this.getToken();
        log.info("当前token：{}", token);
        // 4.发送模板卡片 230927 地址发生变化
        ResponseResultVO<JSONObject> res = HttpUtils.post(config.getUniformSend() + token, new HashMap<String, Object>(4) {{

//            新加POST数据示例如下 240712
            put("touser", map.get("publicOpenId") + "");
            put("template_id", config.getTemplateId());
            put("miniprogram", new HashMap<String, Object>(4) {{
                put("appid", config.getAppId());
                //用户点击公众号推送消息跳转小程序单据详情页 orderType  里面存放json字符串数据
                //判断InvoiceParam
                if (map.containsKey("otherParam")) {
                    put("pagepath", "pages/login/login?loginType=" + map.get("loginType").toString() + "&otherParam=" + map.get("otherParam").toString());
                } else {
                    put("pagepath", "pages/login/login?loginType=" + map.get("loginType").toString());
                }
            }});
            put("data", new HashMap<String, Object>(16) {{
                put("first", new HashMap<String, Object>(4) {{
                    put("value", map.get("first").toString());
                    put("color", "#173177");
                }});
                List<String> keywordList = (List<String>) map.get("keywordList");
                //lambda foreach 取下标
                IntStream.range(0, keywordList.size()).forEach(i -> {
                    String keyIndex = "keyword" + (i + 1);
                    put(keyIndex, new HashMap<String, Object>(4) {{
                        put("value", keywordList.get(i));
                        put("color", "#173177");
                    }});
                });
                put("remark", new HashMap<String, Object>(4) {{
                    put("value", map.get("remark").toString());
                    put("color", "#173177");
                }});
            }});

        }});
        if (res.getCode() == ResponseCodeEnum.SUCCESS.getCode() && res.getData().getString("errcode").equals("0")) {
            log.info("推送成功：{}");
            return ResponseResultUtil.success();
        } else {
            log.error("推送失败：{}", res.getData().toJSONString());
            return ResponseResultUtil.error(res.getData().toJSONString());
        }
    }

    /**
     * @desc : 向用户推送小程序订阅消息方法
     * @author : 刘尧
     * @date : 2024-07-19 08:56
     * */
    public ResponseResultVO<?> wxMessagePush(String messId, JSONObject data, Map<String, Object> map) {
        // 获取微信Token
        String wxToken = getWxToken();
        Map<String, Object> params = new HashMap<>();
        // 接口调用凭证
        params.put("access_token", wxToken);
        // 所需下发的订阅模板id
        params.put("template_id", messId);
        // 点击模板卡片后的跳转页面
        if (map.containsKey("otherParam")) {
            params.put("page", "pages/welcome/welcome?loginType=" + map.get("loginType").toString() + "&otherParam=" + map.get("otherParam").toString());
        } else {
            params.put("page", "pages/welcome/welcome?loginType=" + map.get("loginType").toString());
        }
        // 接收者（用户）的 openid
        params.put("touser", map.get("userWxId"));
        // 跳转小程序类型：developer为开发版；trial为体验版；formal为正式版；
        params.put("miniprogram_state", "trial");
        // 配置模板中明细值
        params.put("data", data);

        ResponseResultVO<JSONObject> post = HttpUtils.post("https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + wxToken, params);
        return post;
    }

    /**
     * @author : jyh
     * @date : 2023-10-11 16:23
     * @desc : 调用中控服务获取公众号的token
     */
    public String getWxPublicAccountToken() {
        JSONObject json = new JSONObject();
        //有效期30天，最大可设置30天
        json.put("appId", config.getWxPublicAccountAppId());
        json.put("appSecret", config.getWxPublicAccountAppSecret());
        ResponseResultVO<JSONObject> res = HttpUtils.post(config.getWechatUrlToken(),
                new HashMap<String, Object>() {{
                    put("appId", config.getWxPublicAccountAppId());
                    put("appSecret", config.getWxPublicAccountAppSecret());
                }});
//        ResponseResultVO<JSONObject> res = HttpUtils.post(config.getWechatUrlToken(),json);
        if (res.getCode() == 200 && JSON.parseObject(JSON.toJSONString(res.getData())).get("code").toString().equals("200")) {
            return JSON.parseObject(JSON.toJSONString(res.getData())).get("data").toString();
        } else {
            throw new BaseBusinessException(ResponseCodeEnum.OPERATE_FAIL.getCode(), res.getMessage());
        }
    }

    /**
     * @desc : 发送跟进任务消息
     * @author : 姜永辉
     * @date : 2022-06-30 19:24
     */
    public String sendFollowPlanMessage(FollowPlan followPlan) {
        log.info("sendFollowMessage:{}", JSONObject.toJSONString(followPlan));
        // 跟进人
        StaffResponse followStaff = staffMapper.selectById(followPlan.getFollowUser());

        Customer customer = customerMapper.selectById(new CustomerQuery().setCusId(followPlan.getCusId()));

        if (customer != null) {
            // 小程序消息


            return null;
        } else {
            return ResponseCodeEnum.SELECT_NULL.getMessage();
        }
    }


    /**
     * @desc : 保存跟进信息到xxl job
     * @author : 于继渤海
     * @date : 2022-05-27 09:53
     */
    @Transactional(rollbackFor = {Exception.class})
    public void saveToXxlJob(CusFollow cusFollow) {
        //设置ID
        Map<String, Object> uniqueNoteCode = commonService.getUniqueNoteCode(Constant.docNameConstant.FOLLOWPLAN.getName(), true);
        String nextId = uniqueNoteCode.get("outId").toString();

        // 约量尺 && 接受邀约
//        预约量尺，邀约结果接受，通知设计师提醒时间是(服务时间)；邀约结果拒绝，通知创建者提醒时间是(提醒时间)
        if (Constant.BasicDataConstant.FOLLOW_STATUS_3.getValue().equals(cusFollow.getFollowStatus()) &&
                Constant.BasicDataConstant.FOLLOW_INVITE_RESULT.getValue().equals(cusFollow.getInviteResult())) {
            cusFollow.setNextFollowTime(cusFollow.getInviteTime()).setFollowStaff(cusFollow.getDesignStaff());
        }

        int id = xxlJobUtils.create(Math.toIntExact(
                (cusFollow.getNextFollowTime().toInstant(ZoneOffset.of("+8")).toEpochMilli() - System.currentTimeMillis()) / 1000
        ), nextId, Constant.XxlJobInfo.FOLLOW.getValue());
        // 生成主键
        followPlanMapper.insert(
                new FollowPlan().setPlanId(nextId).setCusId(cusFollow.getCusId())
                        .setPlanType(Constant.IntegerConstant.PLAN_TYPE_FOLLOW.getValue())
                        .setFollowId(cusFollow.getFollowId())
                        .setFollowUser(cusFollow.getFollowStaff())
                        .setNextFollowPlan(cusFollow.getNextFollowPlan())
                        .setNextFollowTime(cusFollow.getNextFollowTime())
                        .setCallStatus(Constant.CallStatus.CALL_STATUS_UN_DONE.getName() + "")
                        .setXxlJobId(id)
                        .setOpAppCode(Constant.AppCode.WEIXIN.getCode() + "")
                        .setCpId(cusFollow.getCpId())
        );
    }

    /**
     * @desc : 新建量尺回执
     * @author : 于继渤
     * @date : 2023/1/5 9:39
     */
    @Transactional(
            rollbackFor = {Exception.class}
    )
    public ResponseResultVO<?> saveMeasure(CusFollowVO cusFollowVO) {
        CusFollow cusFollow = cusFollowConvert.convertToPo(cusFollowVO);
        //更新总单
        //  int update = cusFollowMapper.updateMeasure(cusFollow);
        //更新客户信息
        Customer customer = new Customer();
        customer.setCusId(cusFollowVO.getCusId());
        customer.setCusName(cusFollowVO.getCusName());
        customer.setCusPhone(cusFollowVO.getCusPhone());

        customer.setAddressName(cusFollowVO.getAddressName());
        customer.setAddressNo(cusFollowVO.getAddressNo());
        customer.setAddressFull(cusFollowVO.getAddressFull()); //全路径地址
        customer.setAddressArea(cusFollowVO.getAddressArea()); //省市区
        customer.setAddressGcj02(cusFollowVO.getAddressGcj02());//经纬度
        customerService.updateByUuid(customer);


        CusFollow Follow = cusFollowMapper.selectById(cusFollowVO.getFollowId());
        if (Follow == null) {
            return ResponseResultUtil.error(ResponseCodeEnum.SELECT_NULL);
        } else if (Constant.BasicDataConstant.MEASURE_STATUS_1.getValue().equals(Follow.getMeasureStatus())) {
            return ResponseResultUtil.error(ErrorCodeEnum.CUSTOMER_FOLLOW_MEASURE_STATUS_DONE.getCode(),
                    ErrorCodeEnum.CUSTOMER_FOLLOW_MEASURE_STATUS_DONE.getMessage());
        }

        StaffEntity staff = authUtils.getStaff();

        //设置id
        Map<String, Object> uniqueNoteCode = commonService.getUniqueNoteCode(Constant.docNameConstant.RECEIPT.getName(), true);
        // 新建一条量尺记录
        MeasureReceipt measureReceipt = new MeasureReceipt();
        if (cusFollowVO.getFlgAgainMeasure() != null) {
            measureReceipt.setFlgAgainMeasure(cusFollowVO.getFlgAgainMeasure());
        } else {
            measureReceipt.setFlgAgainMeasure(false);
        }

        measureReceipt.setReceiptId(uniqueNoteCode.get("outId").toString());
        measureReceipt.setCusId(cusFollowVO.getCusId());
        measureReceipt.setFollowId(cusFollowVO.getFollowId());
        measureReceipt.setMeasureStatus(Constant.BasicDataConstant.MEASURE_STATUS_1.getValue());
        measureReceipt.setMeasureTime(LocalDateTime.now());
        measureReceipt.setMeasureRemarks(cusFollowVO.getMeasureRemarks());
        //剩下参数有前台传
        measureReceiptService.insert(measureReceipt);

        //     新建空间
        if (cusFollowVO.getMeasureRoomList() != null && cusFollowVO.getMeasureRoomList().size() > 0) {
            for (MeasureRoom measureRoom : cusFollowVO.getMeasureRoomList()) {
                //设置ID
                Map<String, Object> uniqueNoteCode1 = commonService.getUniqueNoteCode(Constant.docNameConstant.ROOM.getName(), true);
                measureRoom.setRoomId(uniqueNoteCode1.get("outId").toString());
                measureRoom.setFollowId(cusFollowVO.getFollowId());
                measureRoom.setCusId(cusFollowVO.getCusId());
                measureRoom.setCpId(authUtils.getStaff().getCpId());
                measureRoom.setReceiptId(measureReceipt.getReceiptId());
                measureRoomService.insert(measureRoom);
            }
        }

        //修改量尺状态为  已量尺
        cusFollow.setMeasureStatus(Constant.BasicDataConstant.MEASURE_STATUS_1.getValue());
        //修改跟进
        super.updateByUuid(cusFollow);
        return ResponseResultUtil.success();
    }


    /**
     * @desc : 编辑量尺回执
     * @author : 于继渤
     * @date : 2023/1/5 9:39
     */
    @Transactional(
            rollbackFor = {Exception.class}
    )
    public ResponseResultVO<?> updateMeasure(MeasureReceiptVO measureReceipt) {
        //     新建空间
        if (measureReceipt.getMeasureRoomList() != null && measureReceipt.getMeasureRoomList().size() > 0) {

            for (MeasureRoom measureRoom : measureReceipt.getMeasureRoomList()) {
                if (measureRoom.getRoomId() != null) {
                    measureRoomMapper.deleteByUuid(measureRoom.getRoomId());
                    //设置ID
                    Map<String, Object> uniqueNoteCode1 = commonService.getUniqueNoteCode(Constant.docNameConstant.ROOM.getName(), true);
                    measureRoom.setRoomId(uniqueNoteCode1.get("outId").toString());
                    measureRoom.setFollowId(measureReceipt.getFollowId());
                    measureRoom.setCusId(measureReceipt.getCusId());
                    measureRoom.setCpId(authUtils.getStaff().getCpId());
                    measureRoom.setReceiptId(measureReceipt.getReceiptId());
                    measureRoomService.insert(measureRoom);
                }


            }
            MeasureReceipt measureReceipt1 = measureReceiptConvert.convertToPo(measureReceipt);
            measureReceiptService.updateByUuid(measureReceipt1);
        }
        return ResponseResultUtil.success();
    }


    /**
     * @desc : 编辑
     * @author : 于继渤
     * @date : 2024-03-13 17:03
     */
    @Transactional(rollbackFor = {Exception.class})
    public ResponseResultVO<?> update(CusFollowVO cusFollowVO) {
        CusFollow cusFollow = cusFollowConvert.convertToPo(cusFollowVO);

        //编辑时更改客户意向要把对应客户也需要更改
        if (cusFollowVO.getSaleStatus() != null && (cusFollowVO.getSaleStatus().equals(Constant.saleCustomerStatusConstant.SALE_STATUS_INTE.getName()) || cusFollowVO.getSaleStatus().equals(Constant.saleCustomerStatusConstant.SALE_STATUS_LOST.getName()))) {
            //公海客户清空跟进人
            if (cusFollowVO.getSaleStatus().equals(Constant.saleCustomerStatusConstant.SALE_STATUS_INTE.getName())) {
                customerMapper.updateFollowStaffs(new Customer().setCusId(cusFollowVO.getCusId()).setFollowStaffs(null));
            }
        }
        if (cusFollowVO.getCusId() != null) {
            Customer customer = new Customer();
            customer.setCusId(cusFollowVO.getCusId());
            customer.setAddressName(cusFollowVO.getAddressName());
            customer.setAddressNo(cusFollowVO.getAddressNo());
            customer.setCusPhone(cusFollowVO.getCusPhone());
            customer.setCusName(cusFollowVO.getCusName());
            customer.setOrgId(cusFollowVO.getFollowOrg());
            customer.setAddressFull(cusFollowVO.getAddressFull());
            customer.setAddressArea(cusFollowVO.getAddressArea());
            customer.setSaleStatus(cusFollowVO.getSaleStatus());
            customer.setAddressGcj02(cusFollowVO.getAddressGcj02());
            //更新客户信息
            customerService.updateByUuid(customer);
        } else {
            //不是陌生接待
            if (!cusFollowVO.getFollowStatus().equals(Constant.BasicDataConstant.FOLLOW_STATUS_4.getValue())) {
                StaffEntity staff = authUtils.getStaff();
                Customer customer = new Customer();
                customer.setCusName(cusFollowVO.getCusName());
                customer.setCusPhone(cusFollowVO.getCusPhone());
                customer.setAddressName(cusFollowVO.getAddressName());
                customer.setAddressNo(cusFollowVO.getAddressNo());
                customer.setOrgId(cusFollowVO.getFollowOrg());
                customer.setAddressFull(cusFollowVO.getAddressFull());
                customer.setAddressArea(cusFollowVO.getAddressArea());
                customer.setSaleStatus(cusFollowVO.getSaleStatus());
                customer.setAddressGcj02(cusFollowVO.getAddressGcj02());
                customer.setReportStaff(cusFollowVO.getFollowStaff());
                customer.setReportTime(LocalDateTime.now());
                customer.setCpId(staff.getCpId());
                List<String> list = new ArrayList<>();
                list.add(staff.getStaffId());
                customer.setFollowStaffs(list);
                customer.setSaleStatus("客成状态-潜客");
                customer.setChannelId(cusFollowVO.getChannelId());
                Map<String, Object> customerNoteCode = commonService.getUniqueNoteCode(Constant.docNameConstant.CUSTOMER.getName(), true);
                customer.setCusId(customerNoteCode.get("outId").toString());
                //新建客户
                customerMapper.insert(customer);
                cusFollow.setCusId(customer.getCusId());
            }

        }
        //更新总单
        super.updateByUuid(cusFollow);
        return ResponseResultUtil.success();

    }

    public ResponseResultVO<List<Map>> selectCusFollow(CusFollowQuery cusFollowQuery) {
        return ResponseResultUtil.success(cusFollowMapper.selectCusFollow(cusFollowQuery));
    }

    /**
     * @desc : 构造消息推送模板中data值
     * @author : 刘尧
     * @date : 2024-07-19 08:56
     * */
    private static Map<String, Object> createDataItem(String name, String value) {
        Map<String, Object> item = new HashMap<>();
        item.put(name, value);
        return item;
    }

    /**
     * @desc : 微信公众平台后台配置测试用
     * @author : 刘尧
     * @date : 2024-07-19 08:56
     * */
    public void wxMessageTest(HttpServletRequest request, HttpServletResponse response) {
        String signature = request.getParameter("signature");
        String timestamp = request.getParameter("timestamp");

        String nonce = request.getParameter("nonce");

        String echostr = request.getParameter("echostr");
        // 和小程序后台配置的token保持一致
        String token = config.getMiniMessageToken();
        // 将下面三个参数拼接成字符串
        StringBuffer content = new StringBuffer();
        content.append(timestamp);
        content.append(nonce);
        content.append(token);
        PrintWriter out = null;
        try {
            out = response.getWriter();
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            // 对拼接好的字符串进行sha1加密
            byte[] digest = md.digest(content.toString().getBytes());
            String tmpStr = byteToStr(digest);
            //获得加密后的字符串与signature对比
            if (tmpStr != null && tmpStr.equals(signature.toUpperCase())){
                out.print(echostr);
                out.flush();
            }
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            out.close();
        }
    }

    /**
     * @desc : 获取微信小程序后台Token
     * @author : 刘尧
     * @date : 2024-07-19 08:56
     * */
    private String getWxToken(){
        String appId = config.getAppId();
        String appSecret = config.getAppSecret();
        ResponseResultVO<JSONObject> tokenRes = HttpUtils.get("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret);
        JSONObject data = tokenRes.getData();
        return String.valueOf(data.get("access_token"));
    }

    /**
     * @desc : 将字节转化为十六进制字符串
     * @author : 刘尧
     * @date : 2024-07-19 08:56
     * */
    private static String byteToStr(byte[] byteArray) {
        String strDigest = "";
        for (int i = 0; i < byteArray.length; i++) {
            strDigest += byteToHexStr(byteArray[i]);
        }
        return strDigest;
    }

    /**
     * @desc : 将字节转换成对应的两位十六进制字符串
     * @author : 刘尧
     * @date : 2024-07-19 08:56
     * */
    private static String byteToHexStr(byte mByte) {
        char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
                'B', 'C', 'D', 'E', 'F' };
        char[] tempArr = new char[2];
        tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
        tempArr[1] = Digit[mByte & 0X0F];
        String s = new String(tempArr);
        return s;
    }
}
