package com.fs.app.taskService.impl;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.fs.app.taskService.SopLogsChatTaskService;
import com.fs.fastGpt.param.SendHookAIParam;
import com.fs.qw.domain.QwUser;
import com.fs.qw.mapper.QwUserMapper;
import com.fs.qw.service.IQwExternalContactInfoService;
import com.fs.qw.vo.QwChatSopTempSetting;
import com.fs.qw.vo.QwSopRuleTimeVO;
import com.fs.qwHookApi.param.QwHookSendMsgParam;
import com.fs.sop.domain.QwSop;
import com.fs.sop.domain.QwSopTempRules;
import com.fs.sop.domain.SopUserLogsInfo;
import com.fs.sop.mapper.QwSopLogsMapper;
import com.fs.sop.mapper.QwSopMapper;
import com.fs.sop.mapper.SopUserLogsInfoMapper;
import com.fs.sop.service.IQwSopLogsService;
import com.fs.sop.service.IQwSopTempRulesService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SopLogsChatTaskServiceImpl implements SopLogsChatTaskService {


    @Autowired
    private QwSopMapper sopMapper;

    @Autowired
    private IQwSopLogsService qwSopLogsService;

    @Autowired
    private IQwSopTempRulesService qwSopTempRulesService;

    @Autowired
    private QwSopLogsMapper qwSopLogsMapper;

    @Autowired
    private IQwExternalContactInfoService qwExternalContactInfoService;
    @Autowired
    private SopUserLogsInfoMapper sopUserLogsInfoMapper;
    @Autowired
    private QwUserMapper qwUserMapper;
    @Autowired
    RedisTemplate<String, String> redisTemplate;

    /**
     * 查询所有的AIsop任务
     * @throws Exception
     */
    @Override
    public void createAiChatSopLogs(LocalDateTime today) throws Exception {
        long startTimeMillis = System.currentTimeMillis();
        List<QwSop> sopByChats = sopMapper.selectChatQwSopList();

        CountDownLatch sopLatch = new CountDownLatch(sopByChats.size());
        if (sopByChats.isEmpty()) {
            log.info("没有需要处理的 Ai对话SOP 任务。");
            return;
        }
        for (QwSop sop : sopByChats) {
            processAiChatSopAsync(sop, sopLatch,today);
        }

        // 等待所有 SOP 分组处理完成
        sopLatch.await();

        long endTimeMillis = System.currentTimeMillis();
        log.info("====== Ai对话SOP 日志处理完成，耗时 {} 毫秒 ======", (endTimeMillis - startTimeMillis));
    }

    @Async("sopChatTaskExecutor")
    @Retryable(
            value = { Exception.class },
            maxAttempts = 3,
            backoff = @Backoff(delay = 2000)
    )
    public void processAiChatSopAsync(QwSop sop, CountDownLatch latch,LocalDateTime today) {
        try {
            processAiChatSop(sop,today);
        } catch (Exception e) {
            log.error("处理 SOP ID {} 时发生异常: {}", sop.getId(), e.getMessage(), e);
        } finally {
            latch.countDown();
        }
    }

    /**
     * 查询任务中对应模板
     * @throws Exception
     */
    private void processAiChatSop(QwSop sop,LocalDateTime today) throws Exception {
        QwSopRuleTimeVO ruleTimeVO = sopMapper.selectQwSopByClickHouseId(sop.getId());
        List<QwSopTempRules> rulesList = qwSopTempRulesService.listByTempId(ruleTimeVO.getTempId());
        if (rulesList.isEmpty()) {
            log.warn("SOP ID {} 的 TempSetting 为空，跳过处理。", sop.getId());
            return;
        }
        String[] userIdArray  = sop.getQwUserIds().split(",");

        List<String> qwIds = Arrays.asList(userIdArray);

        List<QwUser> qwUsers = qwUserMapper.selectQwUserByUserIds(qwIds);

        CountDownLatch userLogsLatch = new CountDownLatch(qwUsers.size());
        for (QwUser qwUser : qwUsers) {
            processAiChatUserLogInfoAsync(qwUser, ruleTimeVO, rulesList, userLogsLatch,sop,today);
        }

        // 等待所有用户日志处理完成
        try {
            userLogsLatch.await();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("等待用户日志处理完成时被中断: {}", e.getMessage(), e);
        }
        log.info("SOP ID {} 的所有用户日志已处理完毕。", sop.getId());
    }


    /**
     * 处理chatSop消息
     */
    @Async("sopChatTaskExecutor")
    @Retryable(
            value = { Exception.class },
            maxAttempts = 3,
            backoff = @Backoff(delay = 2000)
    )
    public void processAiChatUserLogInfoAsync(QwUser qwUser, QwSopRuleTimeVO ruleTimeVO, List<QwSopTempRules> tempSettings, CountDownLatch latch,QwSop sop,LocalDateTime today) {
        try {
            processAiChatUserInfoLog(qwUser, tempSettings,today);
        } catch (Exception e) {
            log.error("处理用户日志 {} 时发生异常: {}", qwUser.getId(), e.getMessage(), e);
        } finally {
            latch.countDown();
        }
    }

    private List<QwChatSopTempSetting.Content> getDay(List<QwSopTempRules> tempSettings, long days){
        List<QwSopTempRules> collect = tempSettings.stream().filter(e -> e.getDayNum() == days).collect(Collectors.toList());
        return collect.stream().map(e -> {
            QwChatSopTempSetting.Content content = new QwChatSopTempSetting.Content();
            content.setType(e.getType());
            content.setContentType(e.getContentType() != null ? e.getContentType().toString() : null);
            content.setSetting(e.getSettingList().stream().map(s -> JSON.parseObject(s.getContent(), QwChatSopTempSetting.Content.Setting.class)).collect(Collectors.toList()));
            content.setTime(e.getTime());
            return content;
        }).collect(Collectors.toList());
    }

    private void processAiChatUserInfoLog(QwUser qwUser, List<QwSopTempRules> tempSettings,LocalDateTime today){
        List<SopUserLogsInfo> sopUserLogsInfos = sopUserLogsInfoMapper.selectChatSopUserLogsByQwUserId(qwUser.getQwUserId(), qwUser.getCorpId());
        for (SopUserLogsInfo sopUserLogsInfo : sopUserLogsInfos) {
            String crtTime = sopUserLogsInfo.getCrtTime();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime createTime = LocalDateTime.parse(crtTime, formatter);

            int size = tempSettings.size();
            if (size>0){
                    //第一天的
                    List<QwChatSopTempSetting.Content> content = getDay(tempSettings, 1);
                    for (QwChatSopTempSetting.Content settCont : content) {
                        List<QwChatSopTempSetting.Content.Setting> setting = settCont.getSetting();
                        for (QwChatSopTempSetting.Content.Setting s1 : setting) {
                            LocalDateTime plusTime = createTime.plusMinutes(s1.getIntervalTime());
                            boolean sameMinute = today.withSecond(0).withNano(0).isEqual(plusTime.withSecond(0).withNano(0));
                            if(sameMinute) {
//                            log.info("发送新客消息内容："+s1.getValue());
                            if (s1.getTalkType()!=null&& !s1.getTalkType().isEmpty()){
                                qwExternalContactInfoService.updateQwExternalContactInfoBytalk(s1.getTalkType(),sopUserLogsInfo.getExternalId());
                            }
                            QwHookSendMsgParam sendMsgParam=new QwHookSendMsgParam();
                            QwHookSendMsgParam.QwHookSendMsgData sendMsgData=new QwHookSendMsgParam.QwHookSendMsgData();
                            sendMsgParam.setType(101003);
                            sendMsgData.setMsg(s1.getValue());
                            sendMsgData.setOpenId(sopUserLogsInfo.getExternalContactId());
                            sendMsgData.setSyncKey("1");
                            sendMsgParam.setData(sendMsgData);
                            SendHookAIParam sendAIParam = new SendHookAIParam();
                            sendAIParam.setCmd("aiReplyMsg");
                            sendAIParam.setData(JSONUtil.toJsonStr(sendMsgParam));
                            sendAIParam.setKey(qwUser.getAppKey());
                            redisTemplate.opsForList().leftPush("AiMsg:"+qwUser.getAppKey(), JSON.toJSONString(sendAIParam));
                            }
                        }
                    }


            }


        }

    }

}
