package com.fs.qw.service;

import com.alibaba.fastjson.JSON;
import com.fs.common.utils.StringUtils;
import com.fs.common.utils.date.DateUtil;
import com.fs.company.service.ICompanyMiniappService;
import com.fs.course.config.CourseConfig;
import com.fs.course.domain.FsCourseLink;
import com.fs.course.domain.FsCourseRealLink;
import com.fs.course.domain.FsCourseWatchLog;
import com.fs.course.mapper.FsCourseLinkMapper;
import com.fs.course.mapper.FsCourseWatchLogMapper;
import com.fs.course.utils.FsCourseWatchLogProjectFiller;
import com.fs.fastGpt.domain.FastGptChatReplaceWords;
import com.fs.fastGpt.mapper.FastGptChatReplaceWordsMapper;
import com.fs.qw.domain.QwCompany;
import com.fs.qw.domain.QwExternalContact;
import com.fs.qw.domain.QwExternalContactInfo;
import com.fs.qw.domain.QwUser;
import com.fs.qw.mapper.QwExternalContactInfoMapper;
import com.fs.qw.mapper.QwExternalContactMapper;
import com.fs.qw.vo.QwSopRuleTimeVO;
import com.fs.qw.vo.QwSopTempSetting;
import com.fs.sop.domain.QwSopLogs;
import com.fs.sop.domain.QwSopTempContent;
import com.fs.sop.domain.QwSopTempVoice;
import com.fs.sop.mapper.QwSopLogsMapper;
import com.fs.sop.mapper.QwSopMapper;
import com.fs.sop.mapper.QwSopTempContentMapper;
import com.fs.sop.params.QwSopAutoByTags;
import com.fs.sop.service.IQwSopLogsService;
import com.fs.sop.service.IQwSopTempVoiceService;
import com.fs.sop.service.impl.SopUserLogsInfoServiceImpl;
import com.fs.system.service.ISysConfigService;
import com.fs.voice.utils.StringUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
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.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
@AllArgsConstructor
public class AsyncQwAiChatSopService {

    private static final String miniappRealLink = "/pages_course/video.html?course=";

    @Autowired
    private QwSopMapper qwSopMapper;

    @Autowired
    private QwSopTempContentMapper qwSopTempContentMapper;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    private SopUserLogsInfoServiceImpl sopUserLogsInfoService;
    @Autowired
    private FastGptChatReplaceWordsMapper fastGptChatReplaceWordsMapper;

    @Autowired
    private FsCourseWatchLogMapper fsCourseWatchLogMapper;
    @Autowired
    private FsCourseWatchLogProjectFiller fsCourseWatchLogProjectFiller;
    @Autowired
    private QwExternalContactMapper qwExternalContactMapper;

    @Autowired
    private QwSopLogsMapper qwSopLogsMapper;

    @Autowired
    private IQwSopLogsService qwSopLogsService;

    @Autowired
    private FsCourseLinkMapper fsCourseLinkMapper;

    @Autowired
    private IQwCompanyService iQwCompanyService;

    @Autowired
    private ICompanyMiniappService companyMiniappService;


    @Autowired
    private IQwSopTempVoiceService sopTempVoiceService;

    @Autowired
    private QwExternalContactInfoMapper qwExternalContactInfoMapper;

    @Async("threadPoolTaskExecutor")
    public void executeQwAiChatSop(QwSopAutoByTags qwSopAutoByTags, String userID,
                                   QwUser qwUser, String externalUserID, String externalContactName,
                                   Long externalId, Long fsUserId, LocalDate currentDate, LocalTime localTime) {


        QwExternalContact contact;
        if(externalId != null){
            contact = qwExternalContactMapper.selectById(externalId);
        } else {
            contact = null;
        }
        //新客对话任务
        List<QwSopRuleTimeVO> qwSopAiRuleTimeVOS = qwSopMapper.selectQwAiSopAutoByTagsByForeach(qwSopAutoByTags);
        List<FastGptChatReplaceWords> words = fastGptChatReplaceWordsMapper.selectAllFastGptChatReplaceWords();
        List<QwSopLogs> sopLogsList = new ArrayList<>(Collections.emptyList());


        String json = configService.selectConfigByKey("course.config");
        CourseConfig config = JSON.parseObject(json, CourseConfig.class);

        if (config == null) {
            log.error("配置为空-新客对话创建失败");
            return ;
        }

        QwCompany qwCompany = iQwCompanyService.getQwCompanyByRedis(qwUser.getCorpId());

        if (qwCompany == null ) {
            log.error("企业微信主体未配置默认小程序-新客对话创建失败");
            return ;
        }

        if (qwSopAiRuleTimeVOS != null && !qwSopAiRuleTimeVOS.isEmpty()){

            qwSopAiRuleTimeVOS.forEach(item->{

                List<QwSopTempContent> tempContentList = qwSopTempContentMapper.selectQwSopTempContentByTempIdAndRules(item.getTempId());

                tempContentList.forEach(content->{
                    QwSopLogs sopLogs = new QwSopLogs();
                    sopLogs.setQwUserKey(qwUser.getId());
                    sopLogs.setQwUserid(userID);
                    sopLogs.setExternalUserId(externalUserID);
                    sopLogs.setExternalId(externalId);
                    sopLogs.setLogType(2);
                    sopLogs.setSendStatus(3L);
                    sopLogs.setCompanyId(qwUser.getCompanyId());
                    sopLogs.setReceivingStatus(0L);
                    sopLogs.setSopId(item.getId());
                    sopLogs.setCorpId(qwUser.getCorpId());
                    sopLogs.setFsUserId(fsUserId);
                    sopLogs.setSort(99999999);
                    sopLogs.setSendType(4);
                    sopLogs.setExternalUserName(externalContactName);

                    List<QwSopTempSetting.Content.Setting> settingList =new ArrayList<>();
                    QwSopTempSetting.Content.Setting setting = JSON.parseObject(content.getContent(), QwSopTempSetting.Content.Setting.class);
                    setting.applyRandomTextValue();

                    LocalDateTime dateTime = LocalDateTime.of(currentDate, localTime);
                    LocalDateTime expiryDateTime = dateTime.plusMinutes(setting.getIntervalTime());
                    String sendTime = DateUtil.formatLocalDateTime(expiryDateTime);
                    sopLogs.setSendTime(sendTime);

                    Date expirySendTime = Date.from(expiryDateTime.atZone(ZoneId.of("Asia/Shanghai")).toInstant());

                    //过滤违禁词
                    if ("1".equals(setting.getContentType())) {
                        sopUserLogsInfoService.replaceContent(setting.getContentType(), setting.getValue(), setting::setValue, words); // 替换 value
                    }
                    //过滤违禁词
                    if ("3".equals(setting.getContentType())) {
                        sopUserLogsInfoService.replaceContent(setting.getContentType(), setting.getLinkTitle(), setting::setLinkTitle, words); // 替换 linkTitle
                        sopUserLogsInfoService.replaceContent(setting.getContentType(), setting.getLinkDescribe(), setting::setLinkDescribe, words); // 替换 linkTitle
                    }
                    switch (setting.getContentType()) {
                        //文字和短链一起
                        case "1":
                        case "3":

                            if ("1".equals(setting.getContentType())) {
                                String defaultName = "同学";
                                if(contact != null && StringUtils.isNotEmpty(contact.getName()) && !"待同步客户".equals(contact.getName())){
                                    defaultName = contact.getName();
                                }
                                setting.setValue(setting.getValue()
                                        .replaceAll("#销售称呼#", StringUtil.strIsNullOrEmpty(qwUser.getWelcomeText()) ? "" : qwUser.getWelcomeText())
                                        .replaceAll("#客户称呼#", contact == null || StringUtil.strIsNullOrEmpty(contact.getStageStatus())|| "0".equals(contact.getStageStatus())?defaultName:contact.getStageStatus()));
                            }


                            break;
                        //小程序单独
                        case "4":
                            addWatchLogIfNeededByNewChat(item.getId(), content.getVideoId(), content.getCourseId(), fsUserId,qwUser.getId(), qwUser.getCompanyUserId(), qwUser.getCompanyId(),
                                    externalId, sendTime, expirySendTime,2);

                            String linkByMiniApp = createLinkByMiniAppByNewChat(setting.getExpiresDays(), qwUser.getCorpId(), expirySendTime, content.getCourseId(), content.getVideoId(),
                                    qwUser.getId(), String.valueOf(qwUser.getCompanyUserId()),String.valueOf(qwUser.getCompanyId()), externalId, config);


                            setting.setMiniprogramAppid(qwCompany.getMiniAppId());

                            String miniprogramTitle = setting.getMiniprogramTitle();
                            int maxLength = 17;
                            setting.setMiniprogramTitle(miniprogramTitle.length() > maxLength ? miniprogramTitle.substring(0, maxLength)+"..." : miniprogramTitle);
                            setting.setMiniprogramPage(linkByMiniApp);
                            break;
                        case "7":

                            createVoiceUrlByNewChat(setting, qwUser.getCompanyUserId());
                            break;
                        default:
                            break;

                    }

                    fillFileNameForFileSetting(setting);

                    settingList.add(setting);

                    QwSopTempSetting.Content clonedContent=new QwSopTempSetting.Content();
                    clonedContent.setContentType(setting.getContentType());
                    clonedContent.setCourseId(Long.valueOf(content.getCourseId()));
                    clonedContent.setVideoId(Long.valueOf(content.getVideoId()));
                    clonedContent.setSetting(settingList);
                    clonedContent.setType(content.getType());
                    Integer ruleCourseType = content.getCourseType();
                    clonedContent.setCourseType(ruleCourseType != null ? ruleCourseType : 0);
                    sopLogs.setContentJson(JSON.toJSONString(clonedContent));
                    sopLogsList.add(sopLogs);
                });


            });

            //批量插入 发送记录
            if (!sopLogsList.isEmpty()) {
                processAndInsertQwSopLogsBySendMsg(sopLogsList);
            }
        }

    }

    private void processAndInsertQwSopLogsBySendMsg(List<QwSopLogs> sopLogsList) {
        // 定义批量插入的大小
        int batchSize = 500;

        // 循环处理外部用户 ID，每次处理批量大小的子集
        for (int i = 0; i < sopLogsList.size(); i += batchSize) {

            int endIndex = Math.min(i + batchSize, sopLogsList.size());
            List<QwSopLogs> batchList = sopLogsList.subList(i, endIndex);  // 获取当前批次的子集

            // 直接使用批次数据进行批量更新，不需要额外的 List
            try {
                qwSopLogsService.applyBlacklistCheck(batchList);
                qwSopLogsMapper.batchInsertQwSopLogsOneTouch(batchList);
            } catch (Exception e) {
                // 记录异常日志，方便后续排查问题
                log.error("批量执行一键群发时发生异常，处理的批次起始索引为: " + i, e);
            }
        }
    }

    /** contentType=5 时若没有 fileName，则从 fileUrl 取最后一段文件名，使 content_json 与完课福利等场景字段一致 */
    private void fillFileNameForFileSetting(QwSopTempSetting.Content.Setting setting) {
        if (setting == null || !"5".equals(setting.getContentType())) {
            return;
        }
        if (StringUtils.isNotBlank(setting.getFileName()) || StringUtils.isBlank(setting.getFileUrl())) {
            return;
        }
        String fileUrl = setting.getFileUrl();
        int slash = fileUrl.lastIndexOf('/');
        if (slash < 0 || slash >= fileUrl.length() - 1) {
            return;
        }
        String name = fileUrl.substring(slash + 1);
        int q = name.indexOf('?');
        if (q >= 0) {
            name = name.substring(0, q);
        }
        setting.setFileName(name);
    }

    //插入观看记录
    private Long addWatchLogIfNeededByNewChat(String sopId, Integer videoId, Integer courseId,
                                     Long fsUserId, Long qwUserId, Long companyUserId,
                                     Long companyId, Long externalId, String startTime, Date createTime,Integer watchType) {

        try {
            FsCourseWatchLog watchLog = new FsCourseWatchLog();
            watchLog.setVideoId(Long.valueOf(videoId));
            watchLog.setQwExternalContactId(externalId);
            watchLog.setSendType(2);
            watchLog.setQwUserId(qwUserId);
            watchLog.setSopId(sopId);
            watchLog.setDuration(0L);
            watchLog.setCourseId(Long.valueOf(courseId));
            watchLog.setCompanyUserId(companyUserId);
            watchLog.setCompanyId(companyId);
            watchLog.setCreateTime(createTime);
            watchLog.setUpdateTime(createTime);
            watchLog.setLogType(3);
            watchLog.setUserId(fsUserId);
            watchLog.setWatchType(watchType);
            watchLog.setCampPeriodTime(sopUserLogsInfoService.convertStringToDate(startTime, "yyyy-MM-dd HH:mm:ss"));

            // 企微看课补齐 project，避免按项目完播统计丢失
            fsCourseWatchLogProjectFiller.fillIfAbsent(watchLog);
            //存看课记录
            fsCourseWatchLogMapper.insertOrUpdateFsCourseWatchLog(watchLog);
            return watchLog.getLogId();
        } catch (Exception e) {
            log.error("一键群发失败-插入观看记录失败：" + e.getMessage());
            return null;
        }
    }

    private String createLinkByMiniAppByNewChat(Integer expiresDays, String corpId, Date sendTime,
                                                Integer courseId, Integer videoId, Long qwUserId,
                                       String companyUserId, String companyId, Long externalId, CourseConfig config) {

        try {
            FsCourseLink link = sopUserLogsInfoService.createFsCourseLink(corpId, sendTime, courseId, videoId, qwUserId,
                    companyUserId, companyId, externalId, 3, null);

            FsCourseRealLink courseMap = new FsCourseRealLink();
            BeanUtils.copyProperties(link, courseMap);

            String courseJson = JSON.toJSONString(courseMap);
            String realLinkFull = miniappRealLink + courseJson;
            link.setRealLink(realLinkFull);

            Date updateTime = createUpdateTimeByNewChat(expiresDays, sendTime, config);

            link.setUpdateTime(updateTime);
            //存短链-
            fsCourseLinkMapper.insertFsCourseLink(link);
            return link.getRealLink();
        }catch (Exception e){
            log.error("创建新客对话短链失败：{}|{}|{}|{}|{}", corpId, sendTime, courseId, videoId, qwUserId);
            log.error("e",e);
        }
            return null;
    }

    public Date createUpdateTimeByNewChat(Integer expiresDays, Date sendTime, CourseConfig config) {


        Integer expDays = (expiresDays == null || expiresDays == 0)
                ? config.getVideoLinkExpireDate()
                : expiresDays;

//         使用 Java 8 时间 API 计算过期时间
        LocalDateTime sendDateTime = sendTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        LocalDateTime expireDateTime = sendDateTime.plusDays(expDays - 1);
        expireDateTime = expireDateTime.toLocalDate().atTime(23, 59, 59);
        Date updateTime = Date.from(expireDateTime.atZone(ZoneId.systemDefault()).toInstant());

        return updateTime;
    }

    private void createVoiceUrlByNewChat(QwSopTempSetting.Content.Setting setting, Long companyUserId) {
        QwSopTempVoice qwSopTempVoice = sopTempVoiceService.selectQwSopTempVoiceByCompanyUserIdAndVoiceTxt(companyUserId, setting.getValue());
        if (qwSopTempVoice != null && qwSopTempVoice.getVoiceUrl() != null && qwSopTempVoice.getRecordType() == 1) {
            setting.setVoiceUrl(qwSopTempVoice.getVoiceUrl());
            setting.setVoiceDuration(String.valueOf(qwSopTempVoice.getDuration()));
        } else if (qwSopTempVoice == null) {
            if(companyUserId != null && setting.getValue() != null){
                qwSopTempVoice = new QwSopTempVoice();
                qwSopTempVoice.setCompanyUserId(companyUserId);
                qwSopTempVoice.setVoiceTxt(setting.getValue());
                qwSopTempVoice.setRecordType(0);
                sopTempVoiceService.insertQwSopTempVoice(qwSopTempVoice);
            }
        }
    }

    /**
     * 在职转接 -AI用户信息 一起转
     */
    @Async("threadPoolTaskExecutor")
    public void executeQwSopJobTransfer(Long externalContactId, Long externalId){
        try {
            QwExternalContactInfo contactInfo = qwExternalContactInfoMapper.selectQwExternalContactInfoByExternalContactId(externalContactId);
            if (contactInfo != null) {
                contactInfo.setExternalContactId(externalId);
                qwExternalContactInfoMapper.insertQwExternalContactInfo(contactInfo);
            }
        }catch (Exception e){
            log.error("在职转接-转接客户AI信息失败:{},{}",externalContactId,externalId,e);
        }

    }


}
