package com.fs.course.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.fs.common.utils.DateUtils;
import com.fs.company.mapper.CompanyUserMapper;
import com.fs.course.domain.FsCourseFinishTemp;
import com.fs.course.domain.FsCourseWatchLog;
import com.fs.course.mapper.FsCourseFinishTempMapper;
import com.fs.course.service.IFsCourseFinishTempService;
import com.fs.course.vo.FsCourseFinishTempListVO;
import com.fs.course.vo.FsCourseFinishTempVO;
import com.fs.fastGpt.domain.FastGptChatReplaceWords;
import com.fs.fastGpt.mapper.FastGptChatReplaceWordsMapper;
import com.fs.qw.domain.QwCourseFinishRemarkRty;
import com.fs.qw.domain.QwExternalContact;
import com.fs.qw.domain.QwUser;
import com.fs.qw.mapper.QwExternalContactMapper;
import com.fs.qw.mapper.QwUserMapper;
import com.fs.qw.service.IQwCourseFinishRemarkRtyService;
import com.fs.qw.service.IQwExternalContactService;
import com.fs.qw.service.impl.QwExternalContactServiceImpl;
import com.fs.qw.vo.QwSopCourseFinishTempSetting;
import com.fs.qw.vo.QwUserVO;
import com.fs.qwApi.domain.QwExternalContactRemarkResult;
import com.fs.qwApi.param.QwExternalContactRemarkParam;
import com.fs.qwApi.service.QwApiService;
import com.fs.voice.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 完课模板Service业务层处理
 *
 * @author fs
 * @date 2024-12-19
 */
@Slf4j
@Service
public class FsCourseFinishTempServiceImpl implements IFsCourseFinishTempService
{
    @Autowired
    private FsCourseFinishTempMapper fsCourseFinishTempMapper;

    @Autowired
    private FastGptChatReplaceWordsMapper fastGptChatReplaceWordsMapper;

    @Autowired
    private QwUserMapper qwUserMapper;

    @Autowired
    private CompanyUserMapper companyUserMapper;

    @Autowired
    private IQwExternalContactService iQwExternalContactService;

    @Autowired
    private QwApiService qwApiService;

    @Autowired
    private QwExternalContactMapper qwExternalContactMapper;


    @Autowired
    private IQwCourseFinishRemarkRtyService finishRemarkRtyService;

    /**
     * 查询完课模板
     *
     * @param id 完课模板主键
     * @return 完课模板
     */
    @Override
    public FsCourseFinishTemp selectFsCourseFinishTempById(Long id)
    {
        return fsCourseFinishTempMapper.selectFsCourseFinishTempById(id);
    }

    @Override
    public FsCourseFinishTempVO selectFsCourseFinishTempByIdVO(Long id) {
        FsCourseFinishTempVO fsCourseFinishTemp = fsCourseFinishTempMapper.selectFsCourseFinishTempByIdVO(id);

        String companyUserIds = fsCourseFinishTemp.getCompanyUserIds();
        List<String> qwUserIdsList = Arrays.asList(companyUserIds.split(","));

        List<QwUserVO> qwUserByIds = qwUserMapper.getQwUserByIdsNoCropId(qwUserIdsList);
        fsCourseFinishTemp.setUserSelectList(qwUserByIds);

        return fsCourseFinishTemp;
    }

    /**
     * 查询完课模板列表
     *
     * @param fsCourseFinishTemp 完课模板
     * @return 完课模板
     */
    @Override
    public List<FsCourseFinishTemp> selectFsCourseFinishTempList(FsCourseFinishTemp fsCourseFinishTemp)
    {
        return fsCourseFinishTempMapper.selectFsCourseFinishTempList(fsCourseFinishTemp);
    }

    /**
     * 新增完课模板
     *
     * @param fsCourseFinishTemp 完课模板
     * @return 结果
     */
    @Override
    public int insertFsCourseFinishTemp(FsCourseFinishTemp fsCourseFinishTemp)
    {
        fsCourseFinishTemp.setCreateTime(DateUtils.getNowDate());

        //清理一下违禁词
        fsCourseFinishTemp.setSetting(JSON.toJSONString(processAndReplaceCrouseContent(fsCourseFinishTemp.getSetting())));
        fsCourseFinishTemp.setChatSetting(JSON.toJSONString(processAndReplaceCrouseContent(fsCourseFinishTemp.getChatSetting())));

        return fsCourseFinishTempMapper.insertFsCourseFinishTemp(fsCourseFinishTemp);
    }


    //处理一下违禁词(完课版)
    private List<QwSopCourseFinishTempSetting.Setting>  processAndReplaceCrouseContent(String settingParam){

        List<FastGptChatReplaceWords> words = fastGptChatReplaceWordsMapper.selectAllFastGptChatReplaceWords();
        List<QwSopCourseFinishTempSetting.Setting> list = JSONArray.parseArray(settingParam,QwSopCourseFinishTempSetting.Setting.class);

        //循环内容
        list.forEach(item -> {
            if ("1".equals(item.getContentType())){
                replaceContent(item.getContentType(), item.getValue(), item::setValue, words); // 替换 value
            }

            if ("3".equals(item.getContentType())){
                replaceContent(item.getContentType(), item.getLinkTitle(), item::setLinkTitle, words); // 替换 linkTitle
                replaceContent(item.getContentType(), item.getLinkDescribe(), item::setLinkDescribe, words); // 替换 linkTitle
            }

        });
        return list;
    }
    // 提取通用替换逻辑的方法
    private void replaceContent(String contentType, String content, Consumer<String> setter, List<FastGptChatReplaceWords> words) {
        if (contentType != null && content != null && !content.isEmpty()) {
            for (FastGptChatReplaceWords word : words) {
                if (content.contains(word.getContent())) {
                    // 如果包含目标字段，则替换
                    setter.accept(content.replace(word.getContent(), word.getChangeCount()));
                }
            }
        }
    }

    /**
     * 修改完课模板
     *
     * @param fsCourseFinishTemp 完课模板
     * @return 结果
     */
    @Override
    public int updateFsCourseFinishTemp(FsCourseFinishTemp fsCourseFinishTemp)
    {
        fsCourseFinishTemp.setUpdateTime(DateUtils.getNowDate());
        //清理一下违禁词
        fsCourseFinishTemp.setSetting(JSON.toJSONString(processAndReplaceCrouseContent(fsCourseFinishTemp.getSetting())));

        return fsCourseFinishTempMapper.updateFsCourseFinishTemp(fsCourseFinishTemp);
    }

    /**
     * 批量删除完课模板
     *
     * @param ids 需要删除的完课模板主键
     * @return 结果
     */
    @Override
    public int deleteFsCourseFinishTempByIds(Long[] ids)
    {
        return fsCourseFinishTempMapper.deleteFsCourseFinishTempByIds(ids);
    }

    /**
     * 删除完课模板信息
     *
     * @param id 完课模板主键
     * @return 结果
     */
    @Override
    public int deleteFsCourseFinishTempById(Long id)
    {
        return fsCourseFinishTempMapper.deleteFsCourseFinishTempById(id);
    }

    @Override
    public void deleteByParentIds(Long[] ids) {
        fsCourseFinishTempMapper.deleteByParentIds(ids);
    }

    /**
     * 完课用户 打备注
     */
    @Async
    @Override
    public void finishCourseExtContactIdByRemark(FsCourseWatchLog watchLog) {
        addRandomDelay();
        Long qwExternalContactId = watchLog.getQwExternalContactId();

        Date finishTime = watchLog.getFinishTime();
        LocalDate localDate = finishTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMdd");
        String monthDay = localDate.format(formatter);

        DateTimeFormatter dayFormatter = DateTimeFormatter.ofPattern("dd");
        String dayOfMonth = localDate.format(dayFormatter);

        QwUser qwUserByRedisForId = iQwExternalContactService.getQwUserByRedisForId(String.valueOf(watchLog.getQwUserId()));
        if (qwUserByRedisForId == null || qwUserByRedisForId.getIsSendMsg() == null) {
            log.error("无企微员工信息 {} 跳过处理。", watchLog.getQwUserId());
            return;
        }

        //不用完课备注
        if (qwUserByRedisForId.getIsSendMsg() == 5) {
            log.error("员工不用完课备注 {} 跳过处理。", watchLog.getQwUserId());
            return;
        }

        int isSendMsg = qwUserByRedisForId.getIsSendMsg();

        QwExternalContact externalContact = iQwExternalContactService.selectQwExternalContactByRemark(qwExternalContactId);

        if (externalContact != null) {

            String oldRemark = externalContact.getRemark();
            String newRemark = "";
            String newNotes = "*" + monthDay + "完";
            String newNotesDay = "*" + dayOfMonth + "完";

            if (StringUtil.strIsNullOrEmpty(oldRemark)) {
                oldRemark = externalContact.getName();
            }

            // 2. 提取所有旧标记（无论类型）
            List<String> allOldMarks = new ArrayList<>();
            Pattern markPattern = Pattern.compile("\\*(\\d{1,4})完");
            Matcher markMatcher = markPattern.matcher(oldRemark);
            while (markMatcher.find()) {
                allOldMarks.add(markMatcher.group());
            }

            // 3. 检查是否需要更新
            boolean shouldUpdate = true;

            for (String mark : allOldMarks) {

                String normalizedOldMark = normalizeMarkFormat(mark);
                // 直接比较字符串是否相等
                if (normalizedOldMark.equals(newNotes) ||
                        normalizedOldMark.equals(newNotesDay)) {
                    shouldUpdate = false;
                    break;
                }
            }

            if (!shouldUpdate) {
                return; // 不更新
            }

            // 根据 isSendMsg 决定标记格式
            String markToAdd = (isSendMsg == 3 || isSendMsg == 4) ? newNotesDay : newNotes;

            // 先移除现有标记
            String remarkWithoutMark = oldRemark.replaceAll("\\*\\d{2,4}完", "").trim();

            // 添加新标记（考虑长度限制）
            int keepLength = 20 - markToAdd.length();
            if (keepLength < 0) keepLength = 0;

            if (isSendMsg == 1 || isSendMsg == 3) {
                // 添加到前面
                newRemark = markToAdd + (remarkWithoutMark.length() > keepLength ?
                        remarkWithoutMark.substring(0, keepLength) : remarkWithoutMark);
            } else { // isSendMsg == 2 或 4
                // 添加到后面
                newRemark = (remarkWithoutMark.length() > keepLength ?
                        remarkWithoutMark.substring(0, keepLength) : remarkWithoutMark) + markToAdd;
            }

            QwExternalContactRemarkParam remarkParam = new QwExternalContactRemarkParam();
            remarkParam.setRemark(newRemark);
            remarkParam.setUserid(externalContact.getUserId());
            remarkParam.setExternal_userid(externalContact.getExternalUserId());

//            for (int attempt = 1; attempt <= 2; attempt++) {
            for (int attempt = 1; attempt <= 3; attempt++) { // 增加到3次重试
                try {
                    QwExternalContactRemarkResult qwResult = qwApiService.externalcontactRemark(remarkParam, externalContact.getCorpId());
                    if (qwResult.getErrcode() == 0) {

                        QwExternalContact contactNew = new QwExternalContact();
                        contactNew.setId(externalContact.getId());
                        contactNew.setRemark(newRemark);
                        qwExternalContactMapper.updateQwExternalContact(contactNew);

                        log.info("完课成功添加备注：" + externalContact.getName() + "|" + externalContact.getExternalUserId() + "|" + externalContact.getCorpId() + "|" + externalContact.getUserId() + "|" + newRemark);

                        break;
                    } else {
//                        if (attempt==2 && (qwResult.getErrcode() == 45033 || qwResult.getErrcode()== -1 || qwResult.getErrcode()== 60020 )) {
//                            QwCourseFinishRemarkRty remarkRty=new QwCourseFinishRemarkRty();
//                            remarkRty.setQwUserId(externalContact.getUserId());
//                            remarkRty.setCorpId(externalContact.getCorpId());
//                            remarkRty.setExternalUserId(externalContact.getExternalUserId());
//                            remarkRty.setExternalId(externalContact.getId());
//                            remarkRty.setRemark(newRemark);
//                            remarkRty.setCreateTime(new Date());
//                            finishRemarkRtyService.insertOrUpdateQwCourseFinishRemarkRty(remarkRty);
//
//                        }
//
//                        log.error("完课加备注失败：" + externalContact.getName() + "|" + externalContact.getExternalUserId() + "|" + externalContact.getCorpId() + "|" + externalContact.getUserId() + "|" + newRemark + "|原因" + qwResult.getErrmsg());

                        // 根据错误码智能处理
                        if (isRateLimitError(qwResult.getErrcode())) {
                            // 保存到重试表
                            saveToRetryTable(externalContact, newRemark);

                            // 智能延迟
                            if (attempt < 3) {
                                smartDelayByErrorCode(qwResult.getErrcode(), attempt);
                                continue; // 继续重试
                            }
                        }
                        log.error("完课加备注失败：{}|{}|{}|{}|{}|原因{}",
                                externalContact.getName(), externalContact.getExternalUserId(),
                                externalContact.getCorpId(), externalContact.getUserId(),
                                newRemark, qwResult.getErrmsg());
                    }
                } catch (Exception e) {
//                    log.error("添加备注异常 [尝试第 " + attempt + " 次]：" + externalContact.getName() + "|" + externalContact.getExternalUserId() + "|" + externalContact.getCorpId() + "|" + externalContact.getUserId() + "|" + newRemark + "|" + e.getMessage());
                    log.error("添加备注异常 [尝试第 {} 次]：{}|{}|{}|{}|{}|{}",
                            attempt, externalContact.getName(), externalContact.getExternalUserId(),
                            externalContact.getCorpId(), externalContact.getUserId(),
                            newRemark, e.getMessage());

                    if (attempt < 3) {
                        smartDelayByErrorCode(-1, attempt);
                    }
                }

                // 若不是最后一次尝试，则等待3秒再试
                if (attempt < 2) {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        log.warn("线程等待被中断", e);
                        break;
                    }
                }
            }
        } else {
            log.error("完课加备注失败无客户信息：" + watchLog);
        }


    }

    /**
     * 标准化标记格式，将不同格式统一为标准格式
     * 例如: "*5完" -> "*05完", "*305完" -> "*0305完" (如果是3位数字)
     */
    private String normalizeMarkFormat(String mark) {
        Matcher matcher = Pattern.compile("\\*(\\d{1,4})完").matcher(mark);
        if (matcher.find()) {
            String digits = matcher.group(1);

            // 根据数字长度进行标准化
            switch (digits.length()) {
                case 1: // "*D完" -> "*0D完"
                    return "*0" + digits + "完";
                case 2: // "*DD完" -> 保持不变
                    return mark;
                case 3: // "*DDD完" -> 可能是 "*MDD完" 或 "*DDM完"，统一为4位
                    // 假设是月日格式，补零到4位 "*0MDD完"
                    return "*0" + digits + "完";
                case 4: // "*MMDD完" -> 保持不变
                    return mark;
                default:
                    return mark;
            }
        }
        return mark;
    }

//    @Override
//    public void updateFsCourseFinishTempByCompanyUserId() {
//        List<FsCourseFinishTemp> fsCourseFinishTemps = fsCourseFinishTempMapper.selectFsCourseFinishTempByCompanyList();
//        fsCourseFinishTemps.forEach(item -> {
//            List<String> qwUserList = new ArrayList<>();
//            if (!StringUtil.strIsNullOrEmpty(item.getCompanyUserIds())) {
//                // 分割 companyUserIds 并清理空格
//                Arrays.stream(item.getCompanyUserIds().split("\\s*,\\s*"))
//                        .forEach(userId -> {
//                            if (!StringUtil.strIsNullOrEmpty(userId)){
//                                CompanyUser companyUser = companyUserMapper.selectCompanyUserById(Long.valueOf(userId.trim()));
//                                if (companyUser != null && !StringUtil.strIsNullOrEmpty(companyUser.getQwUserId())) {
//                                    // 分割 qwUserId 并清理空格
//                                    List<String> cleanedQwUserIds = Arrays.stream(companyUser.getQwUserId().split("\\s*,\\s*"))
//                                            .map(String::trim)
//                                            .filter(s -> !s.isEmpty())  // 过滤空字符串
//                                            .collect(Collectors.toList());
//                                    qwUserList.addAll(cleanedQwUserIds);
//                                }
//                            }
//                        });
//                String join = String.join(",", qwUserList);
//                item.setCompanyUserIds(join);
//                fsCourseFinishTempMapper.updateFsCourseFinishTemp(item);
//
//            }
//        });
//    }


    @Override
    public List<FsCourseFinishTempListVO> selectFsCourseFinishTempListVO(FsCourseFinishTemp fsCourseFinishTemp) {
        return fsCourseFinishTempMapper.selectFsCourseFinishTempListVO(fsCourseFinishTemp);
    }

    /**
     * 添加随机延迟，分散请求峰值
     */
    private void addRandomDelay() {
        try {
            // 随机延迟100-500ms，避免同时大量请求
            Thread.sleep(100 + (long)(Math.random() * 400));
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.warn("延迟被中断", e);
        }
    }

    /**
     * 根据错误码智能延迟
     */
    private void smartDelayByErrorCode(Integer errcode, int attempt) {
        try {
            long delayMs;
            if (errcode == 45033) { // 并发限制
                delayMs = 5000 + attempt * 2000L; // 递增延迟
            } else if (errcode == 60020) { // 频率限制
                delayMs = 3000 + attempt * 1000L;
            } else if (errcode == -1) { // 系统繁忙
                delayMs = 2000;
            } else {
                delayMs = 1000; // 默认延迟
            }
            log.info("因错误码 {} 延迟 {}ms", errcode, delayMs);
            Thread.sleep(delayMs);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

    /**
     * 判断是否为频率限制类错误
     */
    private boolean isRateLimitError(Integer errcode) {
        return errcode == 45033 || errcode == 60020 || errcode == -1;
    }

    /**
     * 保存到重试表
     */
    private void saveToRetryTable(QwExternalContact externalContact, String remark) {
        try {
            QwCourseFinishRemarkRty remarkRty=new QwCourseFinishRemarkRty();
            remarkRty.setQwUserId(externalContact.getUserId());
            remarkRty.setCorpId(externalContact.getCorpId());
            remarkRty.setExternalUserId(externalContact.getExternalUserId());
            remarkRty.setExternalId(externalContact.getId());
            remarkRty.setRemark(remark);
            remarkRty.setCreateTime(new Date());
            finishRemarkRtyService.insertOrUpdateQwCourseFinishRemarkRty(remarkRty);
        } catch (Exception e) {
            log.error("保存重试记录失败", e);
        }
    }

    /**
     * 批量更新完课模板状态
     * @param fsCourseFinishTemp
     * @return
     */
    public int updateFsCourseFinishTempBatch(FsCourseFinishTemp fsCourseFinishTemp){
        return fsCourseFinishTempMapper.updateFsCourseFinishTempBatch(fsCourseFinishTemp);
    }
}
