package com.fs.sop.service.impl;

import com.alibaba.fastjson.JSON;
import com.fs.common.core.domain.R;
import com.fs.common.exception.base.BaseException;
import com.fs.common.utils.PubFun;
import com.fs.common.utils.StringUtils;
import com.fs.company.mapper.CompanyUserMapper;
import com.fs.company.vo.CompanyQwUserByIdsVo;
import com.fs.course.mapper.FsCourseWatchLogMapper;
import com.fs.course.service.IFsCourseLinkService;
import com.fs.qw.domain.QwSopUpdateStatus;
import com.fs.qw.domain.QwUser;
import com.fs.qw.mapper.QwUserMapper;
import com.fs.qw.param.QwAutoSopTimeParam;
import com.fs.qw.result.QwFilterSopCustomersResult;
import com.fs.qw.service.impl.AsyncSopService;
import com.fs.qw.service.impl.AsyncSopTestService;
import com.fs.qw.service.impl.AsyncWxSopService;
import com.fs.qw.vo.QwSopRuleTimeVO;
import com.fs.qwApi.Result.QwUploadImgResult;
import com.fs.qwApi.service.QwApiService;
import com.fs.sop.domain.*;
import com.fs.sop.mapper.QwSopLogsMapper;
import com.fs.sop.mapper.QwSopMapper;
import com.fs.sop.mapper.SopUserLogsInfoMapper;
import com.fs.sop.mapper.SopUserLogsMapper;
import com.fs.sop.params.*;
import com.fs.sop.service.*;
import com.fs.sop.vo.SopVoiceListVo;
import com.fs.sop.vo.VoiceVo;
import com.fs.voice.utils.StringUtil;
import com.fs.wxUser.mapper.CompanyWxUserMapper;
import com.fs.wxUser.param.CompanyWxUserSopParam;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 企微sopService业务层处理
 *
 * @author fs
 * @date 2024-07-31
 */
@Service
public class QwSopServiceImpl implements IQwSopService
{
    private static final Logger log = LoggerFactory.getLogger(QwSopServiceImpl.class);

    @Autowired
    private QwSopMapper qwSopMapper;

    @Autowired
    private QwUserMapper qwUserMapper;

    @Autowired
    private QwSopLogsMapper qwSopLogsMapper;

    @Autowired
    private SopUserLogsInfoMapper sopUserLogsInfoMapper;

    @Autowired
    private IFsCourseLinkService iFsCourseLinkService;

    @Autowired
    private FsCourseWatchLogMapper fsCourseWatchLogMapper;

    @Autowired
    private CompanyWxUserMapper companyWxUserMapper;

    @Autowired
    private SopUserLogsMapper sopUserLogsMapper;

    @Autowired
    private AsyncSopService asyncSopService;
    @Autowired
    private AsyncSopTestService asyncSopTestService;
    @Autowired
    private AsyncWxSopService asyncWxSopService;


    @Autowired
    private QwApiService qwApiService;

    @Autowired
    private ISopUserLogsService sopUserLogsService;
    @Autowired
    private CompanyUserMapper companyUserMapper;
    @Autowired
    private IQwSopTempVoiceService qwSopTempVoiceService;
    @Autowired
    private IQwSopTempDayService qwSopTempDayService;
    @Autowired
    private IQwSopTempRulesService qwSopTempRulesService;
    @Autowired
    private IQwSopTempContentService qwSopTempContentService;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 查询企微sop
     *
     * @param id 企微sop主键
     * @return 企微sop
     */
    @Override
    public QwSop selectQwSopById(String id)
    {
        return qwSopMapper.selectQwSopById(id);
    }



    /**
     * 查询企微sop列表
     *
     * @param qwSop 企微sop
     * @return 企微sop
     */
    @Override
    public List<QwSop> selectQwSopList(QwSop qwSop)
    {
        return qwSopMapper.selectQwSopList(qwSop);
    }

    @Override
    public List<QwSop> selectQwSopMyList(QwSop qwSop) {
        return qwSopMapper.selectQwSopMyList(qwSop);
    }

    /**
     * 新增企微sop
     *
     * @param qwSop 企微sop
     * @return 结果
     */
    @Override
    public int insertQwSop(QwSop qwSop)
    {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        qwSop.setCreateTime(sdf.format(new Date()));

        return qwSopMapper.insertQwSop(qwSop);
    }

    /**
     * 修改企微sop
     *
     * @param qwSop 企微sop
     * @return 结果
     */
    @Override
    public R updateQwSop(QwSop qwSop)
    {

        try {

            if (qwSop.getExpiryTime()!=null||qwSop.getIsRating()!=null){
                qwSopMapper.updateQwSop(qwSop);
                return R.ok("修改成功");
            }

            if (StringUtil.strIsNullOrEmpty(qwSop.getId())||StringUtil.strIsNullOrEmpty(qwSop.getTempId())){
                return R.error("sop编号或模板编号不能为空");
            }

            int i = qwSopMapper.updateQwSop(qwSop);
            if (i > 0) {

                    try {
                        rocketMQTemplate.syncSend("voice-generation", JSON.toJSONString(VoiceVo.builder().type(1).id(qwSop.getId()).build()));
                    }catch (Exception e){
                        log.error("修改模板-异步同步临时语音失败:",e);
                    }

                    sopUserLogsMapper.updateSopUserLogsByTempId(qwSop.getTempId(),qwSop.getId());


            }
        }catch (Exception e){
            return  R.error("修改失败-请联系管理员---"+e.getMessage());
        }

        return R.ok();
    }

    @Override
    public int updateAutoSopTime(QwSopAutoTime param) {
        return qwSopMapper.updateAutoSopTime(param);
    }

    @Override
//    @Transactional
    public R updateSopStatus(QwSopUpdateStatus param) {

//        asyncSopTestService.asyncUpdateSopStatus(param);
//        try {
            //如果是2 则是要开启这个sop任务，需要同步 销售营期时间，以及 刷一遍客户营期信息
            if (param.getStatus() == 2) {

                QwSop qwSop = qwSopMapper.selectQwSopById(param.getId());

                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

                // 定义与 startTime 格式一致的 DateTimeFormatter
                DateTimeFormatter formatterDate = DateTimeFormatter.ofPattern("yyyy-MM-dd");

                DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");

                // 2. 将 String 转为 LocalDateTime
                LocalDateTime stopTime = LocalDateTime.parse(qwSop.getStopTime(), formatter);

                // 3. 获取当前系统时间
                LocalDateTime now = LocalDateTime.now();
                LocalDate nowDate = LocalDate.now();
                LocalTime localTime = LocalTime.now();

                // 4. 计算相差天数
                long diffDays = ChronoUnit.DAYS.between(stopTime,now );

                if (diffDays > 0) {

                    List<SopUserLogs> sopUserLogsList = sopUserLogsMapper.selectSopUserLogsBySopId(param.getId());
                    sopUserLogsList.forEach(userLogs->{


                        // 将 startTime 转为 LocalDate
                        LocalDate startDate = LocalDate.parse(userLogs.getStartTime(), formatterDate);

                        // 将 diffDays 加到 startDate 上
                        LocalDate newDate = startDate.plusDays(diffDays);

                        // 将新时间格式化为字符串
                        String newDateStr = newDate.format(formatterDate);

                        userLogs.setStartTime(newDateStr);
                        userLogs.setStatus(1);

                        sopUserLogsMapper.updateSopUserLogsByStartTime(userLogs);

                    });

                }else {
                    SopUserLogs sopUserLogs=new SopUserLogs();
                    sopUserLogs.setStatus(1);
                    sopUserLogs.setSopId(param.getId());
                    //修改营期状态
                    sopUserLogsMapper.updateSopUserLogsByStatus(sopUserLogs);
                }

            }else {
                SopUserLogs sopUserLogs=new SopUserLogs();
                sopUserLogs.setStatus(2);
                sopUserLogs.setSopId(param.getId());
                //修改营期状态
                sopUserLogsMapper.updateSopUserLogsByStatus(sopUserLogs);
            }

            //修改sop任务状态
            qwSopMapper.updateSopStatus(param);

//        }catch (Exception e){
//
//            return R.error("修改执行状态出错了"+e);
//        }

        return R.ok();
    }


    public void qwSopRuleTimeToolsCheckByStop(LocalDate sopStartLocalDate,LocalDate currentDate, DateTimeFormatter dateFormatter,
                                        SopUserLogs userLogs, SopUserLogsInfo logsInfo, SopUserLogsParamByDate userLogsParamByDate,
                                        QwAutoSopTimeParam qwAutoSopTimeParam, DateTimeFormatter timeFormatter, LocalTime localTime) {

        // 还没开始 (未来,不包括今天)
        if (sopStartLocalDate.isAfter(currentDate)) {
            // 大于当前日期，说明还没有开始：
            // -> 以 SOP 任务的开始时间为营期
            String sopStartLocalDateStr = sopStartLocalDate.format(dateFormatter);

            userLogs.setStartTime(sopStartLocalDateStr);
            // 查询开始时间营期表
            String unionSopStartId = sopUserLogsService.selectSopUserLogsByUnionSopId(userLogs);

            // 如果营期表里有，则加入；否则创建新营期
            if (!StringUtil.strIsNullOrEmpty(unionSopStartId)) {
                logsInfo.setUserLogsId(unionSopStartId);
                // 查询这个人是否已在该营期里
                handleInsertSopUserLogsInfo(logsInfo);
            }
            else {
                // 没有营期记录就先插入
                userLogsParamByDate.setStartTime(sopStartLocalDateStr);

                sopUserLogsService.insertSopUserLogsByDate(userLogsParamByDate);

                // 再次查询 拿营期主键
                String unionSopStartIdNew = sopUserLogsService.selectSopUserLogsByUnionSopId(userLogs);
                logsInfo.setUserLogsId(unionSopStartIdNew);

                // 查询是否在营期里，如果没有再插入
                handleInsertSopUserLogsInfo(logsInfo);
            }
        }
        else {
            // sopStartLocalDate <= currentDate -> 说明已经开始
            // -> 以“今天 / 明天”作为营期
            // 获取 AutoSopType
            Integer autoSopType = qwAutoSopTimeParam.getAutoSopType();

            // 今天的日期字符串
            String todayStr = currentDate.format(dateFormatter);
            userLogs.setStartTime(todayStr);

            // 查询今天的营期表
            String unionSopStartId2 = sopUserLogsService.selectSopUserLogsByUnionSopId(userLogs);

            // 明天日期字符串
            LocalDate tomorrowDate = currentDate.plusDays(1);
            String tomorrowStr = tomorrowDate.format(dateFormatter);

            // 复制一份 userLogs，设为明天
            SopUserLogs userLogsTomorrow = new SopUserLogs();
            BeanUtils.copyProperties(userLogs, userLogsTomorrow);
            userLogsTomorrow.setStartTime(tomorrowStr);

            // 复制一份 SopUserLogsParamByDate，设为明天
            SopUserLogsParamByDate paramByDateTomorrow=new SopUserLogsParamByDate();
            BeanUtils.copyProperties(userLogsParamByDate, paramByDateTomorrow);
            paramByDateTomorrow.setStartTime(tomorrowStr);

            // 查询明天的营期表
            String unionTomorrowSopId2 = sopUserLogsService.selectSopUserLogsByUnionSopId(userLogsTomorrow);

            // 根据 autoSopType 分支处理
            switch (autoSopType) {
                // 立即执行
                case 1: {
                    String autoStartTime = qwAutoSopTimeParam.getAutoStartTime();
                    String autoEndTime = qwAutoSopTimeParam.getAutoEndTime();

                    // 如果结束时间为 24:00，则替换成 23:59
                    if ("24:00".equals(autoEndTime)) {
                        autoEndTime = "23:59";
                    }

                    // 转为 LocalTime
                    LocalTime startTime = LocalTime.parse(autoStartTime, timeFormatter);
                    LocalTime endTime = LocalTime.parse(autoEndTime, timeFormatter);

                    // 判断当前时间是否在 [startTime, endTime] 范围内
                    if (!localTime.isBefore(startTime) && !localTime.isAfter(endTime)) {
                        // 在范围内 => 加入到今天的营期
                        if (!StringUtil.strIsNullOrEmpty(unionSopStartId2)) {

                            logsInfo.setUserLogsId(unionSopStartId2);

                            // 查询客户是否已存在
                            handleInsertSopUserLogsInfo(logsInfo);

                        } else {
                            // 没有今天天的营期就先建
                            userLogsParamByDate.setStartTime(todayStr);
                            sopUserLogsService.insertSopUserLogsByDate(userLogsParamByDate);
                            // 查询客户是否已存在
                            SopUserLogsInfo userLogsInfo = sopUserLogsInfoMapper.selectSopUserLogsInfo(logsInfo);
                            if (userLogsInfo == null) {

                                // 再查今天的营期的主键
                                userLogs.setStartTime(todayStr);
                                String unionSopStartIdNew = sopUserLogsService.selectSopUserLogsByUnionSopId(userLogs);

                                logsInfo.setUserLogsId(unionSopStartIdNew);
                                //客户入营期
                                sopUserLogsInfoMapper.insertSopUserLogsInfo(logsInfo);
                            }
                        }
                    } else {
                        // 不在范围内 => 加入到明天的营期
                        if (!StringUtil.strIsNullOrEmpty(unionTomorrowSopId2)) {
                            logsInfo.setUserLogsId(unionTomorrowSopId2);
                            // 查询是否已存在客户入营期
                            handleInsertSopUserLogsInfo(logsInfo);
                        } else {
                            // 没有明天的营期就先建
                            handleNextDayExecution( paramByDateTomorrow, logsInfo, userLogsTomorrow);
                        }
                    }
                    break;
                }
                // 次日执行
                case 2: {
                    // 直接加入到明天的营期没有明天的营期就先建
                    if (!StringUtil.strIsNullOrEmpty(unionTomorrowSopId2)) {
                        logsInfo.setUserLogsId(unionTomorrowSopId2);
                        //客户入营期
                        handleInsertSopUserLogsInfo(logsInfo);
                    } else {
                        // 没有明天的营期就先建
                        handleNextDayExecution( paramByDateTomorrow, logsInfo, userLogsTomorrow);
                    }
                    break;
                }
                default:
                    // 其他类型可根据需要自行扩展
                    break;
            }
        }

    }

    public void handleInsertSopUserLogsInfo(SopUserLogsInfo sopUserLogsInfo){
        SopUserLogsInfo userLogsInfo = sopUserLogsInfoMapper.selectSopUserLogsInfo(sopUserLogsInfo);
        if (userLogsInfo == null) {
            sopUserLogsInfoMapper.insertSopUserLogsInfo(sopUserLogsInfo);
        }
    }

    public void handleNextDayExecution(SopUserLogsParamByDate paramByDateTomorrow,SopUserLogsInfo sopUserLogsInfo,SopUserLogs userLogsTomorrow) {

        sopUserLogsService.insertSopUserLogsByDate(paramByDateTomorrow);

        SopUserLogsInfo userLogsInfo = sopUserLogsInfoMapper.selectSopUserLogsInfo(sopUserLogsInfo);
        if (userLogsInfo == null) {

            String unionTomorrowSopId2New = sopUserLogsService.selectSopUserLogsByUnionSopId(userLogsTomorrow);
            sopUserLogsInfo.setUserLogsId(unionTomorrowSopId2New);

            sopUserLogsInfoMapper.insertSopUserLogsInfo(sopUserLogsInfo);
        }
    }

    /**
     * 批量删除企微sop
     *
     * @param ids 需要删除的企微sop主键
     * @return 结果
     */
    @Override
    public int deleteQwSopByIds(String[] ids)
    {
        //删带待发送记录
        qwSopLogsMapper.deleteQwSopLogsBySopID(ids);
        //删除营期
        sopUserLogsMapper.deleteSopUserLogsBySopIds(ids);
        //删除营期中的客户(不删了)
//        sopUserLogsInfoMapper.deleteSopUserLogsInfoBySopIds(ids);


        return qwSopMapper.deleteQwSopByIdsUpdate(ids);
    }

    /**
     * 删除企微sop信息
     *
     * @param id 企微sop主键
     * @return 结果
     */
    @Override
    public int deleteQwSopById(String id)
    {
        return qwSopMapper.deleteQwSopById(id);
    }


    @Override
    public void checkSopRuleTime() {

        List<QwSopRuleTimeVO> qwSopList = qwSopMapper.checkSopRuleTime();

        CompanyWxUserSopParam wxUserSopParam=new CompanyWxUserSopParam();

        // 获取当前时间
        Date currentTime = new Date();

        // 使用 Calendar 处理时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(currentTime);


        try {
            qwSopList.forEach(ruleTimeVO->{

                //如果当前模板停用了，则不运行了
                if (ruleTimeVO.getTempStatus().equals("0")){
                    QwSop qwSop=new QwSop();
                    qwSop.setId(ruleTimeVO.getId());
                    qwSop.setStatus(0L);

                    qwSopMapper.updateQwSop(qwSop);
                    return;
                }

                //筛选的参数
                QwSopTagsParam qwSopTagsParam = new QwSopTagsParam();

                //录入SOP日志
                QwSopLogs qwSopLogs = new QwSopLogs();

                qwSopLogs.setLogType(ruleTimeVO.getType());
                qwSopLogs.setCompanyId(ruleTimeVO.getCompanyId());
                qwSopLogs.setReceivingStatus(0L);
                qwSopLogs.setSendType(ruleTimeVO.getSendType());
                qwSopLogs.setSopId(ruleTimeVO.getId());
                qwSopLogs.setCorpId(ruleTimeVO.getCorpId());
                qwSopLogs.setSendStatus(3L);


                //规则已经执行
                QwSop qwSop=new QwSop();
                qwSop.setId(ruleTimeVO.getId());
                qwSop.setStatus(2L);
                //标签
                String tags = ruleTimeVO.getTags();

                SopUserLogs sopUserLogs = new SopUserLogs();
                SopUserLogsArray userLogsArray=new SopUserLogsArray();

                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                SimpleDateFormat sdfhms = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

                switch (ruleTimeVO.getType()){
                    //个微
                    case 1:
//                        //客户筛选
//                        wxUserSopParam.setCompanyId(ruleTimeVO.getCompanyId());
//                        wxUserSopParam.setUserIdsSelectList(Arrays.asList( ruleTimeVO.getQwUserIds().split(",")));
//
//                        //标过滤类型
//                        wxUserSopParam.setFilterType(ruleTimeVO.getFilterType());
//
//                        if (!StringUtil.strIsNullOrEmpty(tags)){
//
//                            wxUserSopParam.setTagsIdsSelectList(Arrays.asList(tags.split(",")));
//                        }
//
//                        List<CompanyWxUser> companyWxUserList = companyWxUserMapper.selectCompanyWxUserByCompanyUserId(wxUserSopParam);
//
//                        //如果查询结果为空，则直接返回
//                        if (companyWxUserList == null || companyWxUserList.isEmpty()) {
//                            qwSop.setStatus(3L);
//                            qwSopMapper.updateQwSop(qwSop);
//                            return;
//                        }else {
//
//                            try {
//
//                                Map<String, List<String>> userWeixinMap = companyWxUserList.stream()
//                                        .collect(Collectors.groupingBy(
//                                                res -> String.valueOf(res.getCompanyUserId()), // 按 CompanyUserId 分组
//                                                Collectors.mapping(CompanyWxUser::getWeixinId, Collectors.toList()) // 收集 WeixinId 到列表中
//                                        ));
//                                // 遍历 userWeixinMap
//                                userWeixinMap.forEach((companyUserId, weixinIdList) -> {
//
//                                    SopUserLogsList userLogsList = new SopUserLogsList();
//
//                                    userLogsList.setSopId(ruleTimeVO.getId());
//                                    userLogsList.setSopTempId(ruleTimeVO.getTempId());
//
//                                    userLogsList.setQwUserId(companyUserId);
//                                    userLogsList.setCorpId(ruleTimeVO.getCorpId());
//                                    userLogsList.setStartTime(sdf.format(ruleTimeVO.getStartTime()));
//                                    userLogsList.setStatus(1);
//
//                                    sopUserLogs.setSopId(ruleTimeVO.getId());
//                                    sopUserLogs.setSopTempId(ruleTimeVO.getTempId());
//                                    sopUserLogs.setQwUserId(companyUserId);
//                                    sopUserLogs.setCorpId(ruleTimeVO.getCorpId());
//                                    sopUserLogs.setStartTime(sdf.format(ruleTimeVO.getStartTime()));
//                                    sopUserLogs.setStatus(1);
//                                    //先不弄
////                                    userLogsList.setExternalContactId(weixinIdList);
////                                    String unionSopId = sopUserLogsService.selectSopUserLogsByUnionSopId(sopUserLogs);
////                                    if (!StringUtil.strIsNullOrEmpty(unionSopId)) {
////                                        userLogsArray.setId(unionSopId);
//////                                        userLogsArray.setExternalContactId(weixinIdList.toArray(new String[0]));
////                                        sopUserLogsService.updateSopUserLogsDistinctByList(userLogsArray);
////                                    }else {
////                                        sopUserLogsService.insertSopUserLogsByList(userLogsList);
////                                    }
//
//
//
//                                });
//
//                            }catch (Exception e){
//                                log.error("定时任务执行异常-个微",e);
//                            }
//                        }
//
//                        qwSopMapper.updateQwSop(qwSop);
                        break;
                    //企微
                    case 2:

                        //成员筛选
                        if (!StringUtil.strIsNullOrEmpty(ruleTimeVO.getQwUserIds())){
                            qwSopTagsParam.setUserIdsSelectList(Arrays.asList( ruleTimeVO.getQwUserIds().split(",")));
                        }

                        //标过滤类型
                        qwSopTagsParam.setFilterType(ruleTimeVO.getFilterType());


                        //标签
                        if (!StringUtil.strIsNullOrEmpty(tags)){
                            qwSopTagsParam.setTagsIdsSelectList(Arrays.asList(tags.split(",")));
                        }

                        //排除标签
                        String excludeTags = ruleTimeVO.getExcludeTags();
                        if (!StringUtil.strIsNullOrEmpty(excludeTags)){
                            qwSopTagsParam.setOutTagsIdsSelectList(Arrays.asList(excludeTags.split(",")));
                        }
                        qwSopTagsParam.setCropId(ruleTimeVO.getCorpId());

                        // 查询符合条件的客户
                        List<QwFilterSopCustomersResult> qwFilterSopCustomersResults = qwSopMapper.selectFilterQwSopCustomers(qwSopTagsParam);

                        //如果查询结果为空，则直接返回
                        if (qwFilterSopCustomersResults == null || qwFilterSopCustomersResults.isEmpty()) {
                            qwSop.setStatus(3L);
                            qwSopMapper.updateQwSop(qwSop);
                            return;
                        }

                        //如果是新客对话类型的，则跳过
                        if (ruleTimeVO.getSendType()==4){
                            return;
                        }

                        try {

//                                Map<String, Set<String>> groupedResults = qwFilterSopCustomersResults.stream()
//                                        .collect(Collectors.groupingBy(
//                                                res -> res.getUserId() + "|" + res.getQwUserId() + "|" + res.getCuCompanyUserId() + "|" + res.getCuCompanyId(), // 按 UserId 和 QwUserId 组合的字符串分组
//                                                Collectors.mapping(
//                                                        res -> res.getExternalUserId() + "|" + res.getId()+"|"+res.getFsUserId()+"|"+res.getName(), // 将 ExternalUserId 和 ID 组合成字符串
//                                                        Collectors.toSet() // 收集为列表
//                                                )
//                                        ));

                            Map<String, Set<String>> groupedResults = qwFilterSopCustomersResults.stream()
                                    .collect(Collectors.groupingBy(
                                            res -> res.getUserId().trim() + "|" + res.getQwUserId() + "|" + res.getCuCompanyUserId() + "|" + res.getCuCompanyId(),
                                            Collectors.mapping(
                                                    res -> {
                                                        String name = Optional.ofNullable(res.getName()).orElse("无昵称");
                                                        return res.getExternalUserId().trim() + "|" + res.getId() + "|" + res.getFsUserId() + "|" + name;
                                                    },
                                                    Collectors.toSet() // 收集为 Set
                                            )
                                    ));

                            try {
                                rocketMQTemplate.syncSend("voice-generation", JSON.toJSONString(VoiceVo.builder().type(1).id(ruleTimeVO.getId()).build()));
                                //            new Thread(() -> HttpUtils.sendGet("http://118.24.209.192:8009/qw/voice/synchronousSop", "sopId=" + ruleTimeVO.getId())).start();
                                //            qwSopTempVoiceService.synchronous(ruleTimeVO.getId(), companyUserIds);
                            }catch (Exception e){
                                log.error("异步同步临时语音失败:",e);
                            }

                            groupedResults.forEach((userIdAndQwUserId, externalUserIds) -> {

                                // 将 key 按 "|" 分割，得到 userId 和 qwUserId
                                String[] keys = userIdAndQwUserId.split("\\|"); // 使用 \\| 来转义 | 字符，因为 | 是正则表达式中的特殊字符

                                String userId = keys[0].trim();
                                String qwUserId = keys[1].trim();
                                String companyUserId = keys[2].trim();
                                String companyId = keys[3].trim();

                                SopUserLogsList userLogsList = new SopUserLogsList();

                                userLogsList.setSopId(ruleTimeVO.getId());
                                userLogsList.setSopTempId(ruleTimeVO.getTempId());
                                userLogsList.setQwUserId(userId);
                                userLogsList.setUserId(qwUserId+"|"+companyUserId+"|"+companyId);
                                userLogsList.setCorpId(ruleTimeVO.getCorpId());
                                userLogsList.setStartTime(sdf.format(ruleTimeVO.getStartTime()));
                                userLogsList.setStatus(1);

                                sopUserLogs.setSopId(ruleTimeVO.getId());
                                sopUserLogs.setSopTempId(ruleTimeVO.getTempId());
                                sopUserLogs.setQwUserId(userId);
                                sopUserLogs.setUserId(qwUserId+"|"+companyUserId+"|"+companyId);
                                sopUserLogs.setCorpId(ruleTimeVO.getCorpId());
                                sopUserLogs.setStartTime(sdf.format(ruleTimeVO.getStartTime()));
                                sopUserLogs.setStatus(1);

                                // 主逻辑
                                String unionSopId = sopUserLogsService.selectSopUserLogsByUnionSopId(sopUserLogs);
                                if (!StringUtil.strIsNullOrEmpty(unionSopId)) {
                                    // 如果 unionSopId 存在，直接插入
                                    processAndInsertExternalUserIds(externalUserIds, ruleTimeVO.getId(), unionSopId,userId,ruleTimeVO.getCorpId());
                                } else {
                                    // 否则，先插入 userLogsList
                                    sopUserLogsService.insertSopUserLogsByList(userLogsList);

                                    // 获取新的 unionSopId
                                    String unionSopIdNew = sopUserLogsService.selectSopUserLogsByUnionSopId(sopUserLogs);

                                    // 插入数据
                                    processAndInsertExternalUserIds(externalUserIds, ruleTimeVO.getId(), unionSopIdNew,userId,ruleTimeVO.getCorpId());
                                }

                            });
                        }catch (Exception e){
                            log.error("定时任务执行异常-企微",e);
                        }

                        qwSopMapper.updateQwSop(qwSop);

                        break;
                    default:
                        break;
                }



            });
        }catch (Exception e){
            log.error("定时任务执行失败",e);
        }

    }

    @Override
    public R updateStatusQwSopByIds(String[] ids) {


        List<QwSop> qwSops = qwSopMapper.selectStatusQwSopById(ids);
        List<QwSop> qwSopList = qwSops.stream().filter(e -> e.getType() == 2).collect(Collectors.toList());
        List<QwSop> wxSopList = qwSops.stream().filter(e -> e.getType() == 1).collect(Collectors.toList());

        if(!wxSopList.isEmpty()){
            // 筛选出 status == 1 的 IDs
            String[] toBeSent = wxSopList.stream()
                    .filter(qwSop -> qwSop.getStatus() == 1)
                    .map(QwSop::getId)
                    .toArray(String[]::new);

            // 筛选出 status != 1 的 IDs
            List<String> areadyList = wxSopList.stream()
                    .filter(qwSop -> qwSop.getStatus() != 1)
                    .map(QwSop::getId)
                    .collect(Collectors.toList());

            asyncWxSopService.scheduledWxSopService(toBeSent);

            if (toBeSent.length > 0) {
                int i = qwSopMapper.updateStatusQwSopById(toBeSent);
                if (i > 0) {
                    return R.ok().put("suc",toBeSent).put("err",areadyList);
                }else {
                    return R.error();
                }
            }else {
                return R.error().put("err",areadyList);
            }

        }
        if(!qwSopList.isEmpty()){
            // 筛选出 status == 1 的 IDs
            String[] toBeSent = qwSopList.stream()
                    .filter(qwSop -> qwSop.getStatus() == 1)
                    .map(QwSop::getId)
                    .toArray(String[]::new);

            // 筛选出 status != 1 的 IDs
            List<String> areadyList = qwSopList.stream()
                    .filter(qwSop -> qwSop.getStatus() != 1)
                    .map(QwSop::getId)
                    .collect(Collectors.toList());

            //异步执行
            asyncSopTestService.executeSopByIds(toBeSent);

            if (toBeSent.length > 0) {
                int i = qwSopMapper.updateStatusQwSopById(toBeSent);
                if (i > 0) {
                    return R.ok().put("suc",toBeSent).put("err",areadyList);
                }else {
                    return R.error();
                }
            }else {
                return R.error().put("err",areadyList);
            }
        }
        return R.error();
    }

    @Override
    public R updateMediaImage(String url,String  cropId ) throws IOException {

            QwUploadImgResult uploadimg = qwApiService.uploadimgs(url, cropId);
            if (uploadimg.getErrcode()!=0){
                return R.error("图片上传失败:"+uploadimg.getErrMsg());
            }

            return R.ok().put("data",uploadimg.getUrl());

    }

    @Override
    public List<QwSop> selectAiChatQwSopList(QwSop qwSop) {
        return qwSopMapper.selectAiChatQwSopList(qwSop);
    }

    // 定义一个方法来批量处理插入逻辑，支持每 500 条数据一次的批量插入
    // 定义一个方法来批量处理插入逻辑，支持每 500 条数据一次的批量插入
    private void processAndInsertExternalUserIds(Set<String> externalUserIds, String sopId, String unionSopId, String userId,String corpId) {
        // 定义批量插入的大小
        int batchSize = 500;

        // 将外部用户 ID 转为 List 进行处理
        List<String> externalUserIdsList = new ArrayList<>(externalUserIds);

        // 循环处理外部用户 ID，每次处理批量大小的子集
        for (int i = 0; i < externalUserIdsList.size(); i += batchSize) {
            int endIndex = Math.min(i + batchSize, externalUserIdsList.size());
            List<String> batchList = externalUserIdsList.subList(i, endIndex);  // 获取当前批次的子集

            // 处理当前批次的记录
            List<SopUserLogsInfo> sopUserLogsInfoList = new ArrayList<>();

            batchList.forEach(externalUserId -> {
                // 将 key 按 "|" 分割，得到 userId 和 qwUserId
                String[] externalKeys = externalUserId.split("\\|");

                // 解析 fsUserId
                String fsUserIdStr = (externalKeys[2] != null && !externalKeys[2].trim().equals("null")) ? externalKeys[2].trim() : "";
                Long fsUserId = (!fsUserIdStr.isEmpty()) ? Long.parseLong(fsUserIdStr) : 0L;

                // 解析 externalUserName
                String externalUserName = "无昵称";
                if (externalKeys.length > 3 && externalKeys[3] != null && !externalKeys[3].trim().equals("null") && !externalKeys[3].trim().isEmpty()) {
                    externalUserName = externalKeys[3].trim();
                }
                // 创建 SopUserLogsInfo 对象
                SopUserLogsInfo info = new SopUserLogsInfo();
                info.setSopId(sopId);
                info.setUserLogsId(unionSopId);
                info.setExternalContactId(externalKeys[0].trim());
                info.setQwUserId(userId);
                info.setCorpId(corpId);
                info.setExternalId(Long.valueOf(externalKeys[1].trim()));
                info.setFsUserId(fsUserId);
                info.setExternalUserName(externalUserName);

                // 加入当前批次的列表
                sopUserLogsInfoList.add(info);
            });

            // 批量插入当前批次的数据
            sopUserLogsInfoMapper.batchInsertSopUserLogsInfo(sopUserLogsInfoList);
        }
    }

    @Override
    public R updateSopQwUser(QwSopEditQwUserParam param) {
        QwSop sop = qwSopMapper.selectQwSopById(param.getId());
        if (sop==null){
            return R.error("无此任务");
        }

        try {
            rocketMQTemplate.syncSend("voice-generation", JSON.toJSONString(VoiceVo.builder().type(1).id(sop.getId()).build()));
        }catch (Exception e){
            log.error("修改员工-异步同步临时语音失败:",e);
        }

        String[] updateQwUserIds = param.getQwUserIds().split(",");
        String[] qwUserIds = sop.getQwUserIds().split(",");

        // 将数组转换为集合，方便操作
        Set<String> updateSet = new HashSet<>(Arrays.asList(updateQwUserIds));
        Set<String> originSet = new HashSet<>(Arrays.asList(qwUserIds));

        // 找出新增的数据
        Set<String> addedSet = new HashSet<>(updateSet);
        addedSet.removeAll(originSet);

        // 找出删除的数据
        Set<String> removedSet = new HashSet<>(originSet);
        removedSet.removeAll(updateSet);

        // 找出不变的数据
        Set<String> unchangedSet = new HashSet<>(updateSet);
        unchangedSet.retainAll(originSet);

        //判断新增员工
        if (!addedSet.isEmpty()) {
            processEnterpriseWeChatSop(sop,addedSet);
        }

        //判断删除员工
        if (!removedSet.isEmpty()) {
            deleteSopUserLogsBySet(sop,removedSet);
        }

        //更新SOP内员工
        QwSop sopMap = new QwSop();
        sopMap.setId(param.getId());
        sopMap.setQwUserIds(param.getQwUserIds());
        qwSopMapper.updateQwSop(sopMap);


        System.out.println("新增的数据: " + addedSet);
        System.out.println("删除的数据: " + removedSet);
        System.out.println("不变的数据: " + unchangedSet);


        return R.ok();
    }

    @Override
    public List<SopVoiceListVo> getSopVoiceList(String id) {
        QwSop qwSop = qwSopMapper.selectQwSopById(id);
        if(qwSop == null){
            throw new BaseException("未找到SOP任务");
        }
        List<Long> list = Arrays.stream(qwSop.getQwUserIds().split(",")).filter(StringUtils::isNotEmpty).map(Long::parseLong).collect(Collectors.toList());
        if(list.isEmpty()){
            throw new BaseException("SOP任务暂无企微用户");
        }
        List<CompanyQwUserByIdsVo> companyUserList = companyUserMapper.selectCompanyQwUserByIds(list);
        if(companyUserList.isEmpty()){
            throw new BaseException("未找到账号信息");
        }
        Map<Long, CompanyQwUserByIdsVo> companyMap = PubFun.listToMapByGroupObject(companyUserList, CompanyQwUserByIdsVo::getUserId);
        List<QwSopTempVoice> voiceList = qwSopTempVoiceService.listByTempIdAndCompanyId(qwSop.getTempId(), PubFun.listToNewList(companyUserList, CompanyQwUserByIdsVo::getUserId));
        if(voiceList.isEmpty()){
            return Collections.emptyList();
        }
        List<Long> dayIds = PubFun.listToNewList(voiceList, QwSopTempVoice::getDayId);
        List<QwSopTempDay> dayList = qwSopTempDayService.listById(dayIds);
        Map<Long, QwSopTempDay> dayMap = PubFun.listToMapByGroupObject(dayList, QwSopTempDay::getId);
        List<Long> rulesIds = PubFun.listToNewList(voiceList, QwSopTempVoice::getRuleId);
        List<QwSopTempRules> rulesList = qwSopTempRulesService.listById(rulesIds);
        Map<Long, QwSopTempRules> rulesMap = PubFun.listToMapByGroupObject(rulesList, QwSopTempRules::getId);
        return voiceList.stream().map(e -> {
            QwSopTempDay day = dayMap.get(e.getDayId());
            QwSopTempRules rules = rulesMap.get(e.getRuleId());
            CompanyQwUserByIdsVo company = companyMap.get(e.getCompanyUserId());
            SopVoiceListVo vo = new SopVoiceListVo();
            if(company != null){
                vo.setCompanyUserName(company.getNickName());
                vo.setQwId(company.getQwUserId());
                vo.setQwName(company.getQwUserName());
            }
            if(day != null){
                vo.setName(day.getName());
                vo.setDayNum(day.getDayNum());
            }
            if(rules != null){
                vo.setTime(rules.getTime());
            }
            vo.setVoiceTxt(e.getVoiceTxt());
            vo.setDuration(e.getDuration());
            return vo;
        }).sorted(Comparator.comparing(SopVoiceListVo::getDayNum)).collect(Collectors.toList());
    }

    @Override
    public List<QwSop> selectWxSop() {
        return qwSopMapper.selectWxSop();
    }

    /**
     *新增员工执行SOP
     */
    private void processEnterpriseWeChatSop(QwSop qwSop,Set<String> addedSet) {
        try{
            //如果是新客对话的sop，则不需要找人入营期
            if (qwSop.getSendType()==4){
                return;
            }

            QwSopTagsParam qwSopTagsParam = createQwSopTagsParam(qwSop,addedSet);
            List<QwFilterSopCustomersResult> qwFilterSopCustomersResults = qwSopMapper.selectFilterQwSopCustomers(qwSopTagsParam);

            Map<String, Set<String>> groupedResults = qwFilterSopCustomersResults.stream()
                    .collect(Collectors.groupingBy(
                            res -> res.getUserId().trim() + "|" + res.getQwUserId() + "|" + res.getCuCompanyUserId() + "|" + res.getCuCompanyId(),
                            Collectors.mapping(
                                    res -> {
                                        String name = Optional.ofNullable(res.getName()).orElse("无昵称");
                                        return res.getExternalUserId().trim() + "|" + res.getId() + "|" + res.getFsUserId() + "|" + name;
                                    },
                                    Collectors.toSet()
                            )
                    ));

            groupedResults.forEach((userIdAndQwUserId, externalUserIds) -> {
                String[] keys = userIdAndQwUserId.split("\\|");
                String userId = keys[0].trim();
                String qwUserId = keys[1].trim();
                String companyUserId = keys[2].trim();
                String companyId = keys[3].trim();

                SopUserLogs sopUserLogs = createSopUserLogs(qwSop, userId, qwUserId, companyUserId, companyId);
                SopUserLogsList userLogsList = createSopUserLogsList(qwSop, userId, qwUserId, companyUserId, companyId);

                String unionSopId = sopUserLogsService.selectSopUserLogsByUnionSopId(sopUserLogs);
                if (!StringUtil.strIsNullOrEmpty(unionSopId)) {
                    processAndInsertExternalUserIds(externalUserIds, qwSop.getId(), unionSopId, userId, qwSop.getCorpId());
                } else {
                    sopUserLogsService.insertSopUserLogsByList(userLogsList);
                    String unionSopIdNew = sopUserLogsService.selectSopUserLogsByUnionSopId(sopUserLogs);
                    processAndInsertExternalUserIds(externalUserIds, qwSop.getId(), unionSopIdNew, userId, qwSop.getCorpId());
                }
            });
        }catch (Exception e){
            e.printStackTrace();
            log.error("SOP新增执行员工报错：{}",e.getMessage(),e);
        }

    }

    /**
    * sop任务中-剔除某些员工
    */
    private void deleteSopUserLogsBySet(QwSop qwSop,Set<String> deletedSet) {

        //如果是新客对话的sop，则不需要找人入营期
        if (qwSop.getSendType()==4){
            return;
        }

        deletedSet.forEach(item->{

            QwUser qwUser = qwUserMapper.selectQwUserById(Long.valueOf(item.trim()));

            //删除待发送记录
            qwSopLogsMapper.deleteQwSopLogsByRemoveSop(qwUser.getQwUserId(),qwUser.getCorpId(),qwSop.getId());

            //先查一下之前有没有删除，只保留一条最新的删除数据
            SopUserLogs userLogs=new SopUserLogs();
            userLogs.setSopId(qwSop.getId());
            userLogs.setQwUserId(qwUser.getQwUserId());
            userLogs.setCorpId(qwUser.getCorpId());
            userLogs.setStatus(0);
            List<SopUserLogs> sopUserLogs = sopUserLogsMapper.selectSopUserLogsList(userLogs);
            if(!sopUserLogs.isEmpty()){
                sopUserLogs.forEach(logsVO -> {
                    sopUserLogsMapper.deleteSopUserLogsById(logsVO.getId());
                });

            }

            //删除营期
            sopUserLogsMapper.deleteSopUserLogsByRemoveSop(qwSop.getId(),qwUser.getQwUserId(),qwUser.getCorpId());

            //删除营期中的客户(不动)


        });



    }

    /**
     * 创建标签传参类
     * @return
     */
    private QwSopTagsParam createQwSopTagsParam(QwSop qwSop,Set<String> addedSet) {
        QwSopTagsParam qwSopTagsParam = new QwSopTagsParam();
        //成员筛选
        if (!StringUtil.strIsNullOrEmpty(qwSop.getQwUserIds())){
            qwSopTagsParam.setUserIdsSelectList(addedSet.stream().collect(Collectors.toList()));
        }
        //标过滤类型
        qwSopTagsParam.setFilterType(qwSop.getFilterType());

        //标签
        if (!StringUtil.strIsNullOrEmpty(qwSop.getTags())){
            qwSopTagsParam.setTagsIdsSelectList(Arrays.asList(qwSop.getTags().split(",")));
        }

        //排除标签
        String excludeTags = qwSop.getExcludeTags();
        if (!StringUtil.strIsNullOrEmpty(excludeTags)){
            qwSopTagsParam.setOutTagsIdsSelectList(Arrays.asList(excludeTags.split(",")));
        }
        qwSopTagsParam.setCropId(qwSop.getCorpId());
        return qwSopTagsParam;
    }

    /**
     * 创建营期
     */
    private SopUserLogs createSopUserLogs(QwSop qwSop, String userId, String qwUserId, String companyUserId, String companyId) {
        SopUserLogs sopUserLogs = new SopUserLogs();
        sopUserLogs.setSopId(qwSop.getId());
        sopUserLogs.setSopTempId(qwSop.getTempId());
        sopUserLogs.setQwUserId(userId);
        sopUserLogs.setUserId(qwUserId + "|" + companyUserId + "|" + companyId);
        sopUserLogs.setCorpId(qwSop.getCorpId());
        sopUserLogs.setStartTime(qwSop.getStartTime());
        sopUserLogs.setStatus(1);
        return sopUserLogs;
    }

    /**
     * 创建营期成员
     */
    private SopUserLogsList createSopUserLogsList(QwSop qwSop, String userId, String qwUserId, String companyUserId, String companyId) {
        SopUserLogsList userLogsList = new SopUserLogsList();
        userLogsList.setSopId(qwSop.getId());
        userLogsList.setSopTempId(qwSop.getTempId());
        userLogsList.setQwUserId(userId);
        userLogsList.setUserId(qwUserId + "|" + companyUserId + "|" + companyId);
        userLogsList.setCorpId(qwSop.getCorpId());
        userLogsList.setStartTime(qwSop.getStartTime());
        userLogsList.setStatus(1);
        return userLogsList;
    }


}
