package com.fs.qw.service.impl;

import com.alibaba.fastjson.JSON;
import com.fs.common.utils.PubFun;
import com.fs.course.domain.FsCourseSopAppLink;
import com.fs.course.mapper.FsCourseSopAppLinkMapper;
import com.fs.gtPush.service.uniPush2Service;
import com.fs.qw.domain.QwSopUpdateStatus;
import com.fs.qw.domain.QwUser;
import com.fs.qw.mapper.QwExternalContactMapper;
import com.fs.qw.result.QwFilterSopCustomersResult;
import com.fs.qw.vo.QwSopRuleTimeVO;
import com.fs.qw.vo.QwSopTempSetting;
import com.fs.sop.domain.QwSop;
import com.fs.sop.domain.QwSopTemp;
import com.fs.sop.domain.SopUserLogs;
import com.fs.sop.domain.SopUserLogsInfo;
import com.fs.sop.mapper.*;
import com.fs.sop.params.DeleteQwSopParam;
import com.fs.sop.params.QwSopTagsParam;
import com.fs.sop.params.SopUserLogsList;
import com.fs.sop.service.ISopUserLogsService;
import com.fs.sop.vo.VoiceVo;
import com.fs.store.mapper.FsUserMapper;
import com.fs.voice.utils.StringUtil;
import com.fs.wxUser.param.CompanyWxUserSopParam;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

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;

@Slf4j
@Service
@AllArgsConstructor
public class AsyncSopTestService {


    private final QwSopLogsMapper qwSopLogsMapper;
    private final QwSopMapper qwSopMapper;
    private final FsUserMapper fsUserMapper;
    private final SopUserLogsInfoMapper sopUserLogsInfoMapper;
    private final ISopUserLogsService sopUserLogsService;
    private final QwExternalContactMapper qwExternalContactMapper;
    private final QwSopTempMapper qwSopTempMapper;
    private final RocketMQTemplate rocketMQTemplate;
    private final SopUserLogsMapper sopUserLogsMapper;
    private final FsCourseSopAppLinkMapper fsCourseSopAppLinkMapper;
    private final uniPush2Service push2Service;

    /**
     * 立即执行SOP任务
     */
    @Async("scheduledExecutorService")
    public void executeSopByIds(String[] ids) {
        try {
            List<QwSopRuleTimeVO> ruleTimeVOList = qwSopMapper.executeSopByIds(ids);
            List<QwSopTemp> tempList = qwSopTempMapper.selectListByIds(PubFun.listToNewList(ruleTimeVOList, QwSopRuleTimeVO::getTempId));
            Map<String, QwSopTemp> tempMap = PubFun.listToMapByGroupObject(tempList, QwSopTemp::getId);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

            ruleTimeVOList.forEach(ruleTimeVO -> {
                QwSopTemp qwSopTemp = tempMap.get(ruleTimeVO.getTempId());
                if (qwSopTemp.getStatus().equals("0")) {
                    updateQwSopStatus(ruleTimeVO.getId(), 0L);
                    return;
                }
                processRuleTimeVOInternal(ruleTimeVO, qwSopTemp,sdf);
            });
        } catch (Exception e) {
            e.printStackTrace();
            log.error("立即执行执行失败", e);
        }
    }

    /**
     * 异步执行暂停
     */
    @Async("scheduledExecutorService")
    public void asyncUpdateSopStatus(QwSopUpdateStatus 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) {
            e.printStackTrace();
            log.error("立即执行执行失败", e);
        }
    }

    /**
     * 判断类型
     */
    private void processRuleTimeVOInternal(QwSopRuleTimeVO ruleTimeVO, QwSopTemp qwSopTemp,SimpleDateFormat sdf) {
        QwSop qwSop = createQwSop(ruleTimeVO, 2L);

        switch (ruleTimeVO.getType()) {
            case 1:
                processWeChatSop(ruleTimeVO, qwSop,sdf);
                break;
            case 2:
                processEnterpriseWeChatSop(ruleTimeVO, qwSop,sdf);
                break;
            default:
                break;
        }

        qwSopMapper.updateQwSop(qwSop);
    }


    /**
     * 个微
     */
    private void processWeChatSop(QwSopRuleTimeVO ruleTimeVO, QwSop qwSop,SimpleDateFormat sdf) {
//        CompanyWxUserSopParam wxUserSopParam = createCompanyWxUserSopParam(ruleTimeVO);
//        List<CompanyWxUser> companyWxUserList = companyWxUserMapper.selectCompanyWxUserByCompanyUserId(wxUserSopParam);
//
//        if (companyWxUserList == null || companyWxUserList.isEmpty()) {
//            return;
//        }
//
//        Map<String, List<String>> userWeixinMap = companyWxUserList.stream()
//                .collect(Collectors.groupingBy(
//                        res -> String.valueOf(res.getCompanyUserId()),
//                        Collectors.mapping(companyWxUser -> companyWxUser.getWeixinId().trim(), Collectors.toList())
//                ));
//
//        userWeixinMap.forEach((companyUserId, weixinIdList) -> {
//            SopUserLogs sopUserLogs = createSopUserLogs(ruleTimeVO, companyUserId);
//            SopUserLogsList userLogsList = createSopUserLogsList(ruleTimeVO, companyUserId);
//
//            // 客户列表放新表(先不弄)
//            // userLogsList.setExternalContactId(weixinIdList);
//        });
    }

    /**
     * 企微
     */
    private void processEnterpriseWeChatSop(QwSopRuleTimeVO ruleTimeVO, QwSop qwSop,SimpleDateFormat sdf) {
        QwSopTagsParam qwSopTagsParam = createQwSopTagsParam(ruleTimeVO);
        List<QwFilterSopCustomersResult> qwFilterSopCustomersResults = qwSopMapper.selectFilterQwSopCustomers(qwSopTagsParam);

        if (qwFilterSopCustomersResults == null || qwFilterSopCustomersResults.isEmpty()) {
            qwSop.setStatus(3L);
            qwSopMapper.updateQwSop(qwSop);
            return;
        }

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

        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()
                        )
                ));
        List<List<Long>> companyUserIds = PubFun.listToNewList(qwFilterSopCustomersResults.stream().filter(e -> e.getCuCompanyId() != null && e.getCompanyId() != null).collect(Collectors.toList()), e -> Arrays.asList(e.getCuCompanyUserId(), e.getCuCompanyId()));
        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) -> {
            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(ruleTimeVO, userId, qwUserId, companyUserId, companyId,sdf);
            SopUserLogsList userLogsList = createSopUserLogsList(ruleTimeVO, userId, qwUserId, companyUserId, companyId,sdf);

            String unionSopId = sopUserLogsService.selectSopUserLogsByUnionSopId(sopUserLogs);
            if (!StringUtil.strIsNullOrEmpty(unionSopId)) {
                processAndInsertExternalUserIds(externalUserIds, ruleTimeVO.getId(), unionSopId, userId, ruleTimeVO.getCorpId());
            } else {
                sopUserLogsService.insertSopUserLogsByList(userLogsList);
                String unionSopIdNew = sopUserLogsService.selectSopUserLogsByUnionSopId(sopUserLogs);
                processAndInsertExternalUserIds(externalUserIds, ruleTimeVO.getId(), unionSopIdNew, userId, ruleTimeVO.getCorpId());
            }
        });
    }

    /**
     * 更新SOP状态
     * @param id
     * @param status
     */
    private void updateQwSopStatus(String id, Long status) {
        QwSop qwSop = new QwSop();
        qwSop.setId(id);
        qwSop.setStatus(status);
        qwSopMapper.updateQwSop(qwSop);
    }

    /**
     * 创建标签传参类
     * @param ruleTimeVO
     * @return
     */
    private QwSopTagsParam createQwSopTagsParam(QwSopRuleTimeVO ruleTimeVO) {
        QwSopTagsParam qwSopTagsParam = new QwSopTagsParam();
        //成员筛选
        if (!StringUtil.strIsNullOrEmpty(ruleTimeVO.getQwUserIds())){
            qwSopTagsParam.setUserIdsSelectList(Arrays.asList( ruleTimeVO.getQwUserIds().split(",")));
        }

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


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

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


    /**
     * 创建
     * @param ruleTimeVO
     * @param status
     * @return
     */
    private QwSop createQwSop(QwSopRuleTimeVO ruleTimeVO, Long status) {
        QwSop qwSop = new QwSop();
        qwSop.setId(ruleTimeVO.getId());
        qwSop.setStatus(status);
        return qwSop;
    }

    private CompanyWxUserSopParam createCompanyWxUserSopParam(QwSopRuleTimeVO ruleTimeVO) {
        CompanyWxUserSopParam wxUserSopParam = new CompanyWxUserSopParam();
        wxUserSopParam.setCompanyId(ruleTimeVO.getCompanyId());
        wxUserSopParam.setUserIdsSelectList(Arrays.asList(ruleTimeVO.getQwUserIds().split(",")));
        wxUserSopParam.setFilterType(ruleTimeVO.getFilterType());
        if (!StringUtil.strIsNullOrEmpty(ruleTimeVO.getTags())) {
            wxUserSopParam.setTagsIdsSelectList(Arrays.asList(ruleTimeVO.getTags().split(",")));
        }
        return wxUserSopParam;
    }

    /**
     * 创建营期
     */
    private SopUserLogs createSopUserLogs(QwSopRuleTimeVO ruleTimeVO, String userId, String qwUserId, String companyUserId, String companyId,SimpleDateFormat sdf) {
        SopUserLogs sopUserLogs = new SopUserLogs();
        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);
        return sopUserLogs;
    }

    /**
     * 创建营期成员
     */
    private SopUserLogsList createSopUserLogsList(QwSopRuleTimeVO ruleTimeVO, String userId, String qwUserId, String companyUserId, String companyId,SimpleDateFormat sdf) {
        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);
        return userLogsList;
    }

//    private void processAndInsertExternalUserIds(Set<String> externalUserIds, String sopId, String unionSopId, String userId, String corpId) {
//        // 处理并插入 externalUserIds
//    }

    /**
     *批量插入营期成员
     */
    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);
            });

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

        }
    }


    /**
     * 异步处理销售删除客户
     */
    @Async("scheduledExecutorService")
    public void deleteSop(QwUser qwUser) {

        try {
            //查询这个销售所有的删除的客户
            List<String> deleteList = qwExternalContactMapper.selectQwExternalContactListAllByStatus(qwUser.getQwUserId(), qwUser.getCorpId());

            // 2. 设定每个批次大小
            final int batchSize = 500;

            // 3. 分批调用，避免一次塞太多
            for (int start = 0; start < deleteList.size(); start += batchSize) {
                // 计算此批次的结束位置
                int end = Math.min(start + batchSize, deleteList.size());

                // 获取当前批次需要删除的 externalUserId 子列表
                List<String> subList = deleteList.subList(start, end);

                //删除待发送记录
                DeleteQwSopParam apiParam = new DeleteQwSopParam();
                apiParam.setQwUserId(qwUser.getQwUserId());
                apiParam.setCorpId(qwUser.getCorpId());
                apiParam.setExternalUserIds(subList);

                // 批量删除 qw_external_contact 表中已经删除的客户的营期以及发送记录
                sopUserLogsInfoMapper.deleteByQwUserIdAndCorpIdToContactIdList(apiParam);
                sopUserLogsInfoMapper.deleteByQwUserIdAndCorpIdToContactIdByChatList(apiParam);


                //批量删除发送记录
                qwSopLogsMapper.deleteQwSopLogsByExternalUserIdList(apiParam);
            }

        }catch (Exception e){
            log.error("异步处理销售删除客户:"+e);
        }



    }

    /**
    * 异步录入 app的sop链接信息
    */
    @Async("scheduledExecutorService")
    public void createFsCourseSopAppLink(String link, Date sendTime, Date updateTime, String companyId,
                                            String companyUserId,String qwUserId,String qwUserName,String corpId,
                                            Integer courseId,String linkTile,String linkImageUrl,Integer videoId,
                                            String linkDescribe,String appMsgLink,Long externalId){

        FsCourseSopAppLink sopAppLink=new FsCourseSopAppLink();
        sopAppLink.setLink(link);
        sopAppLink.setCreateTime(sendTime);
        sopAppLink.setUpdateTime(updateTime);
        sopAppLink.setCompanyId(Long.parseLong(companyId));
        sopAppLink.setCompanyUserId(Long.parseLong(companyUserId));
        sopAppLink.setQwUserId(Long.parseLong(qwUserId));
        sopAppLink.setQwUserName(qwUserName);
        sopAppLink.setCorpId(corpId);
        sopAppLink.setCourseId(Long.valueOf(courseId));
        sopAppLink.setCourseTitle(linkTile);
        sopAppLink.setCourseUrl(linkImageUrl);
        sopAppLink.setVideoId(Long.valueOf(videoId));
        sopAppLink.setVideoTitle(linkDescribe);
        sopAppLink.setAppRealLink(appMsgLink);
        sopAppLink.setQwExternalId(externalId);

        fsCourseSopAppLinkMapper.insertFsCourseSopAppLink(sopAppLink);

    }

    /**
     * 异步录入 发送有app的客户
     */
    @Async("scheduledExecutorService")
    public void  asyncSendMsgBySopAppLink(Long externalId,String linkTile,String linkDescribe,String link){
        push2Service.pushSopAppLinkMsgByExternal(externalId,linkTile,linkDescribe,link);
    }

    /**
     * 异步录入 发送有app的客户 之 正常sop版
     */
    @Async("scheduledExecutorService")
    public void  asyncSendMsgBySopAppLinkNormal(List<QwSopTempSetting.Content.Setting> setting,Long externalId){

        setting.forEach(item->{
            push2Service.pushSopAppLinkMsgByExternal(externalId,item.getLinkTitle(),item.getLinkDescribe(),item.getAppLinkUrl());
        });

    }
}
