package com.fs.qw.service.impl;


import com.alibaba.fastjson.JSON;
import com.fs.common.BeanCopyUtils;
import com.fs.common.utils.DateUtils;
import com.fs.qw.domain.QwExternalContact;
import com.fs.qw.domain.QwExternalErrRetry;
import com.fs.qw.domain.QwUser;
import com.fs.qw.mapper.QwExternalContactMapper;
import com.fs.qw.mapper.QwExternalErrRetryMapper;
import com.fs.qw.mapper.QwUserMapper;
import com.fs.qw.param.QwAutoSopTimeParam;
import com.fs.qw.service.IQwExternalErrRetryService;
import com.fs.qw.vo.QwSopRuleTimeVO;
import com.fs.qwApi.domain.QwExternalContactRemarkResult;
import com.fs.qwApi.domain.QwResult;
import com.fs.qwApi.param.QwEditUserTagParam;
import com.fs.qwApi.param.QwExternalContactRemarkParam;
import com.fs.qwApi.service.QwApiService;
import com.fs.sop.domain.SopUserLogs;
import com.fs.sop.domain.SopUserLogsInfo;
import com.fs.sop.mapper.QwSopMapper;
import com.fs.sop.mapper.SopUserLogsInfoMapper;
import com.fs.sop.params.QwSopAutoByTags;
import com.fs.sop.params.SopUserLogsParamByDate;
import com.fs.sop.service.ISopUserLogsService;
import com.fs.voice.utils.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 企业微信客户 添加标签/备注失败重试Service业务层处理
 *
 * @author fs
 * @date 2024-12-26
 */
@Service
public class QwExternalErrRetryServiceImpl implements IQwExternalErrRetryService
{
    @Autowired
    private QwExternalErrRetryMapper qwExternalErrRetryMapper;

    @Autowired
    QwApiService qwApiService;

    @Autowired
    private ISopUserLogsService sopUserLogsService;

    @Autowired
    private SopUserLogsInfoMapper sopUserLogsInfoMapper;

    @Autowired
    private QwUserMapper qwUserMapper;

    @Autowired
    private QwSopMapper qwSopMapper;

    @Autowired
    private QwExternalContactMapper qwExternalContactMapper;

    /**
     * 查询企业微信客户 添加标签/备注失败重试
     *
     * @param id 企业微信客户 添加标签/备注失败重试主键
     * @return 企业微信客户 添加标签/备注失败重试
     */
    @Override
    public QwExternalErrRetry selectQwExternalErrRetryById(Long id)
    {
        return qwExternalErrRetryMapper.selectQwExternalErrRetryById(id);
    }

    /**
     * 查询企业微信客户 添加标签/备注失败重试列表
     *
     * @param qwExternalErrRetry 企业微信客户 添加标签/备注失败重试
     * @return 企业微信客户 添加标签/备注失败重试
     */
    @Override
    public List<QwExternalErrRetry> selectQwExternalErrRetryList(QwExternalErrRetry qwExternalErrRetry)
    {
        return qwExternalErrRetryMapper.selectQwExternalErrRetryList(qwExternalErrRetry);
    }

    /**
     * 新增企业微信客户 添加标签/备注失败重试
     *
     * @param qwExternalErrRetry 企业微信客户 添加标签/备注失败重试
     * @return 结果
     */
    @Override
    public int insertQwExternalErrRetry(QwExternalErrRetry qwExternalErrRetry)
    {
        qwExternalErrRetry.setCreateTime(DateUtils.getNowDate());
        return qwExternalErrRetryMapper.insertQwExternalErrRetry(qwExternalErrRetry);
    }

    /**
     * 修改企业微信客户 添加标签/备注失败重试
     *
     * @param qwExternalErrRetry 企业微信客户 添加标签/备注失败重试
     * @return 结果
     */
    @Override
    public int updateQwExternalErrRetry(QwExternalErrRetry qwExternalErrRetry)
    {
        qwExternalErrRetry.setUpdateTime(DateUtils.getNowDate());
        return qwExternalErrRetryMapper.updateQwExternalErrRetry(qwExternalErrRetry);
    }

    /**
     * 批量删除企业微信客户 添加标签/备注失败重试
     *
     * @param ids 需要删除的企业微信客户 添加标签/备注失败重试主键
     * @return 结果
     */
    @Override
    public int deleteQwExternalErrRetryByIds(Long[] ids)
    {
        return qwExternalErrRetryMapper.deleteQwExternalErrRetryByIds(ids);
    }

    /**
     * 删除企业微信客户 添加标签/备注失败重试信息
     *
     * @param id 企业微信客户 添加标签/备注失败重试主键
     * @return 结果
     */
    @Override
    public int deleteQwExternalErrRetryById(Long id)
    {
        return qwExternalErrRetryMapper.deleteQwExternalErrRetryById(id);
    }

    @Override
    public int qwExternalErrRetryTimer() {
        // 获取当前日期（只包含年月日）
        LocalDate currentDate = LocalDate.now();
        // 获取当前系统时间 (HH:mm)
        LocalTime localTime = LocalTime.now();

        List<QwExternalErrRetry> qwExternalErrRetries = qwExternalErrRetryMapper.qwExternalErrRetryTimer();

        qwExternalErrRetries.forEach(item->{
            switch (item.getRetryState()){
                //标签
                case 1:

                    //新增
                    if (item.getRetryType()==2){

                        QwEditUserTagParam qwEditUserTagParam = JSON.parseObject(item.getRetryParams(), QwEditUserTagParam.class);
                        QwResult qwResult = qwApiService.editUserTag(qwEditUserTagParam, item.getCorpId());

                        if(qwResult.getErrcode() == 0){

                            QwUser qwUser = qwUserMapper.selectQwUserByCorpIdAndUserId(item.getCorpId(), qwEditUserTagParam.getUserid());
                            QwExternalContact contact = qwExternalContactMapper.selectQwExternalByExternalIdAndCompanyIdToIdAndFs(qwEditUserTagParam.getExternal_userid(), qwEditUserTagParam.getUserid(), item.getCorpId());
                            //分时段里符合的标签-再用来创建自动SOP
                            QwSopAutoByTags qwSopAutoByTags=new QwSopAutoByTags();
                            qwSopAutoByTags.setQwUserId(String.valueOf(qwUser.getId()));
                            qwSopAutoByTags.setCorpId(item.getCorpId());
                            qwSopAutoByTags.setTagsIdsSelectList(qwEditUserTagParam.getAdd_tag());
                            qwSopAutoByTags.setSendType(2);
                            List<QwSopRuleTimeVO> qwSopRuleTimeVOS = qwSopMapper.selectQwSopAutoByTagsByForeach(qwSopAutoByTags);

                            if (qwSopRuleTimeVOS != null && !qwSopRuleTimeVOS.isEmpty()){
                                List<String> addTag = qwEditUserTagParam.getAdd_tag();
                                //SOP规则
                                qwSopRuleTimeTools(qwSopRuleTimeVOS, qwEditUserTagParam.getUserid(),qwUser,item.getCorpId(),qwEditUserTagParam.getExternal_userid(),contact.getName(),contact,currentDate,localTime,addTag);

                            }
                            //因为是新客户，所有直接覆盖
                            contact.setTagIds(JSON.toJSONString(qwEditUserTagParam.getAdd_tag()));
                            qwExternalContactMapper.updateQwExternalContact(contact);

                            //从重试表中
                            qwExternalErrRetryMapper.deleteQwExternalErrRetryById(item.getId());
                        }else {
                            item.setRetryNum(item.getRetryNum()+1);
                            item.setRemark(qwResult.getErrmsg());
                            qwExternalErrRetryMapper.updateQwExternalErrRetry(item);
                        }
                    }
                    break;

                //备注
                case 2:

                    //新增
                    if (item.getRetryType()==2){
                        QwExternalContactRemarkParam qwExternalContactRemarkParam = JSON.parseObject(item.getRetryParams(), QwExternalContactRemarkParam.class);

                        QwExternalContactRemarkResult remarkResult = qwApiService.externalcontactRemark(qwExternalContactRemarkParam, item.getCorpId());

                        if(remarkResult.getErrcode() == 0){
                            qwExternalErrRetryMapper.deleteQwExternalErrRetryById(item.getId());
                        }else {
                            item.setRetryNum(item.getRetryNum()+1);
                            qwExternalErrRetryMapper.updateQwExternalErrRetry(item);
                        }
                    }


                    break;

            }
        });
        return 0;
    }


    public void qwSopRuleTimeTools(List<QwSopRuleTimeVO> qwSopRuleTimeVOS, String userID, QwUser qwUser, String corpId,
                                   String externalUserID, String externalContactName, QwExternalContact contact,
                                   LocalDate currentDate,LocalTime localTime,List<String> combinedTagsList) {
        // 定义日期和时间格式化器
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");

        // sop任务
        qwSopRuleTimeVOS.forEach(ruleTimeVO -> {

            // 将排除的字符串转成列表
            List<String> excludedTagsList=new ArrayList<>();
            if (ruleTimeVO.getExcludeTags() != null && !ruleTimeVO.getExcludeTags().isEmpty()){
                excludedTagsList= Arrays.asList( ruleTimeVO.getExcludeTags().split(","));
            }

            // 检查 combinedTagsList 是否包含排除列表中的任意一个标签
            boolean containsExcludedTag = combinedTagsList.stream()
                    .anyMatch(excludedTagsList::contains);

            //含任意一个排除标签
            if (containsExcludedTag) {
                return;
            }

            // 自动sop的规则
            QwAutoSopTimeParam qwAutoSopTimeParam = JSON.parseObject(ruleTimeVO.getAutoSopTime(), QwAutoSopTimeParam.class);

            // 用于查询/或新增
            SopUserLogs userLogs = new SopUserLogs();
            userLogs.setSopId(ruleTimeVO.getId());
            userLogs.setSopTempId(ruleTimeVO.getTempId());
            userLogs.setCorpId(ruleTimeVO.getCorpId());
            userLogs.setStatus(1);

            // 用于今天的新增
            SopUserLogsParamByDate userLogsParamByDate = new SopUserLogsParamByDate();
            userLogsParamByDate.setSopId(ruleTimeVO.getId());
            userLogsParamByDate.setSopTempId(ruleTimeVO.getTempId());
            userLogsParamByDate.setCorpId(ruleTimeVO.getCorpId());
            userLogsParamByDate.setStatus(1);

            // 从数据库中取到的开始时间（Date类型），转换为 LocalDate
            Date sopStartTime = ruleTimeVO.getStartTime();
            //开始时间
            LocalDate sopStartLocalDate = sopStartTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

            // 设定用户信息
            userLogs.setQwUserId(userID);
            userLogs.setUserId(qwUser.getId() + "|" + qwUser.getCompanyUserId() + "|" + qwUser.getCompanyId());
            userLogsParamByDate.setQwUserId(userID);
            userLogsParamByDate.setUserId(qwUser.getId() + "|" + qwUser.getCompanyUserId() + "|" + qwUser.getCompanyId());

            // 创建 SopUserLogsInfo
            SopUserLogsInfo sopUserLogsInfo = new SopUserLogsInfo();
            sopUserLogsInfo.setQwUserId(userID.trim());
            sopUserLogsInfo.setCorpId(qwUser.getCorpId());
            sopUserLogsInfo.setExternalContactId(externalUserID.trim());
            sopUserLogsInfo.setExternalId(contact.getId());
            sopUserLogsInfo.setFsUserId(contact.getFsUserId());
            sopUserLogsInfo.setExternalUserName(externalContactName);
            sopUserLogsInfo.setSopId(ruleTimeVO.getId());

            // 判断 SOP 任务的开始时间是否在当前日期之前
            // 还没开始 (未来)
//            if (!sopStartLocalDate.isBefore(currentDate)) {
            if (sopStartLocalDate.isAfter(currentDate)) {
                // 大于等于当前日期，说明还没有开始：
                // -> 以 SOP 任务的开始时间为营期
                String sopStartLocalDateStr = sopStartLocalDate.format(dateFormatter);

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

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

                    sopUserLogsService.insertSopUserLogsByDate(userLogsParamByDate);

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

                    // 查询是否在营期里，如果没有再插入
                    handleInsertSopUserLogsInfo(sopUserLogsInfo);
                }
            } 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();
                BeanCopyUtils.copy(userLogs, userLogsTomorrow);
                userLogsTomorrow.setStartTime(tomorrowStr);

                // 复制一份 SopUserLogsParamByDate，设为明天
                SopUserLogsParamByDate paramByDateTomorrow=new SopUserLogsParamByDate();
                BeanCopyUtils.copy(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)) {

                                sopUserLogsInfo.setUserLogsId(unionSopStartId2);

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

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

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

                                    sopUserLogsInfo.setUserLogsId(unionSopStartIdNew);
                                    //客户入营期
                                    sopUserLogsInfoMapper.insertSopUserLogsInfo(sopUserLogsInfo);
                                }
                            }
                        } else {
                            // 不在范围内 => 加入到明天的营期
                            if (!StringUtil.strIsNullOrEmpty(unionTomorrowSopId2)) {
                                sopUserLogsInfo.setUserLogsId(unionTomorrowSopId2);
                                // 查询是否已存在客户入营期
                                handleInsertSopUserLogsInfo(sopUserLogsInfo);
                            } else {
                                // 没有明天的营期就先建
                                handleNextDayExecution( paramByDateTomorrow, sopUserLogsInfo, userLogsTomorrow);
                            }
                        }
                        break;
                    }
                    // 次日执行
                    case 2: {
                        // 直接加入到明天的营期没有明天的营期就先建
                        if (!StringUtil.strIsNullOrEmpty(unionTomorrowSopId2)) {
                            sopUserLogsInfo.setUserLogsId(unionTomorrowSopId2);
                            //客户入营期
                            handleInsertSopUserLogsInfo(sopUserLogsInfo);
                        } else {
                            // 没有明天的营期就先建
                            handleNextDayExecution( paramByDateTomorrow, sopUserLogsInfo, 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);
        }
    }
}
