package com.fs.fastGpt.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fs.common.annotation.DataSource;
import com.fs.common.core.domain.entity.SysDictData;
import com.fs.common.enums.DataSourceType;
import com.fs.common.utils.DateUtils;
import com.fs.company.domain.CompanyUser;
import com.fs.company.service.ICompanyService;
import com.fs.fastGpt.domain.FastGptEventTokenLog;
import com.fs.fastGpt.domain.FastGptPushTokenTotal;
import com.fs.fastGpt.domain.FastGptRole;
import com.fs.fastGpt.domain.FastgptEventLogTotal;
import com.fs.fastGpt.mapper.FastgptEventLogTotalMapper;
import com.fs.fastGpt.service.IFastGptRoleService;
import com.fs.fastGpt.service.IFastgptEventLogTotalService;
import com.fs.fastGpt.vo.FastgptEventLogTotalVo;
import com.fs.qw.mapper.QwRestrictionPushRecordMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

import static com.fs.common.utils.DictUtils.getDictCache;

/**
 * ai事件埋点统计Service业务层处理
 *
 * @author fs
 * @date 2025-06-26
 */
@Service
@Slf4j
public class FastgptEventLogTotalServiceImpl extends ServiceImpl<FastgptEventLogTotalMapper, FastgptEventLogTotal> implements IFastgptEventLogTotalService {

    @Autowired
    FastgptEventLogTotalMapper fastgptEventLogTotalMapper;

    @Autowired
    private ICompanyService companyService;

    @Autowired
    private IFastGptRoleService fastGptRoleService;
    /**
     * 查询ai事件埋点统计
     *
     * @param id ai事件埋点统计主键
     * @return ai事件埋点统计
     */
    @Override
    public FastgptEventLogTotal selectFastgptEventLogTotalById(Long id)
    {
        return baseMapper.selectFastgptEventLogTotalById(id);
    }

    /**
     * 查询ai事件埋点统计列表
     *
     * @param fastgptEventLogTotal ai事件埋点统计
     * @return ai事件埋点统计
     */
    @Override
    public List<FastgptEventLogTotal> selectFastgptEventLogTotalList(FastgptEventLogTotal fastgptEventLogTotal)
    {
        return baseMapper.selectFastgptEventLogTotalList(fastgptEventLogTotal);
    }

    /**
     * 新增ai事件埋点统计
     *
     * @param fastgptEventLogTotal ai事件埋点统计
     * @return 结果
     */
    @Override
    public int insertFastgptEventLogTotal(FastgptEventLogTotal fastgptEventLogTotal)
    {
        return baseMapper.insertFastgptEventLogTotal(fastgptEventLogTotal);
    }

    /**
     * 修改ai事件埋点统计
     *
     * @param fastgptEventLogTotal ai事件埋点统计
     * @return 结果
     */
    @Override
    public int updateFastgptEventLogTotal(FastgptEventLogTotal fastgptEventLogTotal)
    {
        return baseMapper.updateFastgptEventLogTotal(fastgptEventLogTotal);
    }

    /**
     * 批量删除ai事件埋点统计
     *
     * @param ids 需要删除的ai事件埋点统计主键
     * @return 结果
     */
    @Override
    public int deleteFastgptEventLogTotalByIds(Long[] ids)
    {
        return baseMapper.deleteFastgptEventLogTotalByIds(ids);
    }

    /**
     * 删除ai事件埋点统计信息
     *
     * @param id ai事件埋点统计主键
     * @return 结果
     */
    @Override
    public int deleteFastgptEventLogTotalById(Long id)
    {
        return baseMapper.deleteFastgptEventLogTotalById(id);
    }

    @Override
    public List<FastgptEventLogTotal> selectFastgptEventLogTotalInfoList(FastgptEventLogTotal logTotal) {
        return fastgptEventLogTotalMapper.selectFastgptEventLogTotalInfoList(logTotal);
    }

    @Override
    public FastgptEventLogTotal selectFastgptEventLogTotalByRoleIdAndType(FastgptEventLogTotal total) {
        return fastgptEventLogTotalMapper.selectFastgptEventLogTotalByRoleIdAndType(total);
    }

    @Override
    public FastgptEventLogTotal selectFastgptEventTokenLogTotalByRoleIdAndType(FastGptEventTokenLog tokenLog) {
        return fastgptEventLogTotalMapper.selectFastgptEventTokenLogTotalByRoleIdAndType(tokenLog);
    }

    @Override
    public FastgptEventLogTotalVo totalFastgptEventLog(List<FastgptEventLogTotalVo> list) {
        FastgptEventLogTotalVo totalVo = new FastgptEventLogTotalVo();
        totalVo.setRoleName("总计");
        Map<Integer, Long> totalMap = new HashMap<>();
        if(list != null && !list.isEmpty()){
            list.forEach(m -> {
                m.getTypeCountMap().forEach((k,v) -> {
                    if(totalMap.containsKey(k)){
                        totalMap.put(k, totalMap.get(k) + v);
                    }else{
                        totalMap.put(k, v);
                    }
                });
            });
            totalVo.setTypeCountMap(totalMap);
            return totalVo;
        }else{
            return null;
        }
    }

    @Override
    public List<FastgptEventLogTotalVo> selectFastgptEventLogTotalVoInfoList(FastgptEventLogTotalVo fastgptEventLogTotal) {
        if(fastgptEventLogTotal.getBeginTime() == null || fastgptEventLogTotal.getEndTime() == null){
            fastgptEventLogTotal.setBeginTime(DateUtil.offsetDay(DateUtil.parse(DateUtils.getDate()), -10).toDateStr());
            fastgptEventLogTotal.setEndTime(DateUtils.getDate());
        }
        String appKey = fastgptEventLogTotal.getAppKey();
        if(appKey != null){
            List<String> roleIds = fastGptRoleService.selectFastGptRoleRoleIdsByAppKey(appKey);
            if(roleIds != null && !roleIds.isEmpty()){
                fastgptEventLogTotal.setRoleIds(roleIds);
                fastgptEventLogTotal.setRoleId(null);
            }else{
                fastgptEventLogTotal.setRoleId(0L);
            }
        }

        if(fastgptEventLogTotal.getUserIds() != null && !fastgptEventLogTotal.getUserIds().isEmpty()){
            List<String> userIds = fastgptEventLogTotal.getUserIds();
            String result = userIds.stream()
                    .filter(userId -> userId.startsWith("user_") && userId.length() > 5)
                    .map(userId -> userId.substring(5))
                    .collect(Collectors.joining(","));
            List<CompanyUser> companyUserList = companyService.selectCompanyListByIds(result);
            String qwUserIds = companyUserList.stream()
                    .map(CompanyUser::getQwUserId)
                    .filter(Objects::nonNull) // 过滤掉 null 的 qwUserId
                    .flatMap(userId -> Arrays.stream(userId.split(","))) // 安全 split
                    .map(String::trim)
                    .distinct() // 去重
                    .collect(Collectors.joining(",")); // 收集为逗号分隔的字符串
            fastgptEventLogTotal.setQwUserIds(qwUserIds);
        }
        List<FastgptEventLogTotal> totalList = fastgptEventLogTotalMapper.selectFastgptEventLogTotalVoInfoList(fastgptEventLogTotal);
        List<SysDictData> dictCache = getDictCache("sys_fastgpt_event_log_type");
        if(dictCache == null){
            return null;
        }
        List<FastgptEventLogTotalVo> totalVoList = new ArrayList<>();
        List<Integer> typeList = new ArrayList<>();
        dictCache.forEach(n -> typeList.add(Integer.parseInt(n.getDictValue())));
        if(totalList != null && !totalList.isEmpty()){
            Map<String, List<FastgptEventLogTotal>> groupedByDateStr = totalList.stream()
                    .collect(Collectors.groupingBy(FastgptEventLogTotal::getStatTime));

            List<Long> roleIds = totalList.stream().map(FastgptEventLogTotal::getRoleId).collect(Collectors.toList());
            List<FastGptRole> fastGptRoles = fastGptRoleService.selectFastGptRoleByRoleIds(roleIds);

            for (String date : groupedByDateStr.keySet()) {
                List<FastgptEventLogTotal> list = groupedByDateStr.get(date);
                Map<Long, List<FastgptEventLogTotal>> roleIdGrouped = list.stream()
                        .collect(Collectors.groupingBy(FastgptEventLogTotal::getRoleId));
                for (Long roleId : roleIdGrouped.keySet()) {
                    List<FastgptEventLogTotal> logTotalList = roleIdGrouped.get(roleId);
                    FastgptEventLogTotalVo eventLogTotalVo = new FastgptEventLogTotalVo();
                    eventLogTotalVo.setRoleId(roleId);
                    eventLogTotalVo.setStatTime(date);
                    List<Integer> types = logTotalList.stream().map(FastgptEventLogTotal::getType).collect(Collectors.toList());
                    typeList.forEach(m -> logTotalList.forEach(n ->{
                        if(types.contains(m)){
                            if(eventLogTotalVo.getTypeCountMap() == null){
                                Map<Integer, Long> map = new HashMap<>();
                                map.put(n.getType(), n.getCount());
                                eventLogTotalVo.setTypeCountMap(map);
                            }else{
                                Map<Integer, Long> countMap = eventLogTotalVo.getTypeCountMap();
                                countMap.put(n.getType(), n.getCount());
                                eventLogTotalVo.setTypeCountMap(countMap);
                            }
                        }else{
                            if(eventLogTotalVo.getTypeCountMap() == null){
                                Map<Integer, Long> map = new HashMap<>();
                                map.put(m, 0L);
                                eventLogTotalVo.setTypeCountMap(map);
                            }else{
                                Map<Integer, Long> countMap = eventLogTotalVo.getTypeCountMap();
                                countMap.put(m, 0L);
                                eventLogTotalVo.setTypeCountMap(countMap);
                            }
                        }
                    }));
                    for (FastGptRole fastGptRole : fastGptRoles) {
                        if(Objects.equals(fastGptRole.getRoleId(), eventLogTotalVo.getRoleId())){
                            eventLogTotalVo.setRoleName(fastGptRole.getRoleName());
                        }
                    }

                    totalVoList.add(eventLogTotalVo);
                }
            }
            totalVoList.sort(Comparator.comparing(FastgptEventLogTotalVo::getStatTime).thenComparing(FastgptEventLogTotalVo::getRoleId).reversed());
            return totalVoList;
        }else{
            return null;
        }
    }

    @Override
    public List<FastGptEventTokenLog> selectFastgptEventTokenLogTotalList(FastGptEventTokenLog fastGptEventTokenLog) {
        return fastgptEventLogTotalMapper.selectFastgptEventTokenLogTotalList(fastGptEventTokenLog);
    }



    public static List<String> generateDateStrings(String startDateStr, int days) {
        List<String> dateList = new ArrayList<>();
        for (int i = 0; i < days; i++) {
            String dateStr = DateUtil.offsetDay(DateUtil.parse(startDateStr), i).toDateStr();
            dateList.add(dateStr);
        }
        return dateList;
    }

    /**
     * 批量新增ai事件埋点统计
     *
     * @param fastgptEventLogTotalList ai事件埋点统计列表
     * @return 结果
     */
    @Override
    public int insertFastgptEventLogTotalBatch(List<FastgptEventLogTotal> fastgptEventLogTotalList) {
        return baseMapper.insertFastgptEventLogTotalBatch(fastgptEventLogTotalList);
    }

    /**
     * 批量修改ai事件埋点统计
     *
     * @param fastgptEventLogTotalList ai事件埋点统计列表
     * @return 结果
     */
    @Override
    public int updateFastgptEventLogTotalBatch(List<FastgptEventLogTotal> fastgptEventLogTotalList) {
        return baseMapper.updateFastgptEventLogTotalBatch(fastgptEventLogTotalList);
    }

    @Override
    public List<FastgptEventLogTotalVo> selectFastgptEventLogTotalListByStatTime(String dateTime) {
        return fastgptEventLogTotalMapper.selectFastgptEventLogTotalListByStatTime(dateTime);
    }

    @Autowired
    private QwRestrictionPushRecordMapper qwRestrictionPushRecordMapper;

    @Autowired
    private IFastgptEventLogTotalService fastgptEventLogTotalService;
    @Override
    /**
     * 统计指定时间段内的ai事件埋点
     * @param startDate 开始日期 (格式: yyyy-MM-dd)
     * @param endDate 结束日期 (格式: yyyy-MM-dd)
     */
    public void eventLogTotals(String startDate, String endDate) {
        try {
            // 解析开始和结束日期
            LocalDate start = LocalDate.parse(startDate);
            LocalDate end = LocalDate.parse(endDate);

            // 循环处理每一天
            LocalDate current = start;
            while (!current.isAfter(end)) {
                String dateTime = current.format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                Date date = Date.from(current.atStartOfDay(java.time.ZoneId.systemDefault()).toInstant());

                log.info("开始处理日期: {}", dateTime);

                // 更新埋点
                processEventLogTotals(date, dateTime);
                // 更新token消耗
                processTokenLogs(date, dateTime);

                // 移动到下一天
                current = current.plusDays(1);
            }

            log.info("时间段 {} 至 {} 的AI事件统计处理完成", startDate, endDate);
        } catch (Exception e) {
            log.error("处理时间段AI事件统计异常，时间范围: " + startDate + " 至 " + endDate, e);
        }
    }

    @Override
    public List<FastgptEventLogTotalVo> selectFastgptEventLogTotalExport(FastgptEventLogTotal fastgptEventLogTotal) {
        return fastgptEventLogTotalMapper.selectFastgptEventLogTotalExport(fastgptEventLogTotal);
    }


    private void processEventLogTotals(Date date, String dateTime) {
        FastgptEventLogTotal logTotal = new FastgptEventLogTotal();
        logTotal.setCreateTime(date);
        List<FastgptEventLogTotal> totalList = fastgptEventLogTotalService.selectFastgptEventLogTotalInfoList(logTotal);

        // 分别收集需要更新和插入的记录
        List<FastgptEventLogTotal> toUpdateList = new ArrayList<>();
        List<FastgptEventLogTotal> toInsertList = new ArrayList<>();

        // 用于防止重复添加相同记录的集合
        Set<String> processedKeys = new HashSet<>();

        for (FastgptEventLogTotal total : totalList) {
            try {
                if (total == null) {
                    continue;
                }

                if (total.getType() == 1) {
                    total.setCount(total.getSenderCount());
                }
                // 构造唯一标识符，用于防止重复处理
                String uniqueKey = String.format("%d_%d_%d_%d_%d_%s",
                        total.getRoleId() != null ? total.getRoleId() : 0,
                        total.getType() != null ? total.getType() : 0,
                        total.getCompanyId() != null ? total.getCompanyId() : 0,
                        total.getCompanyUserId() != null ? total.getCompanyUserId() : 0,
                        total.getQwUserId() != null ? total.getQwUserId() : 0,
                        dateTime
                );
                // 检查是否已经处理过这个记录
                if (processedKeys.contains(uniqueKey)) {
                    continue;
                }

                FastgptEventLogTotal info = fastgptEventLogTotalService.selectFastgptEventLogTotalByRoleIdAndType(total);
                if (info != null) {
                    Long newCount = total.getCount() != null ? total.getCount() : 0L;
                    // 只有当count值发生变化时才加入更新列表
                    if (!newCount.equals(info.getCount())) {
                        FastgptEventLogTotal eventLogTotal = new FastgptEventLogTotal();
                        eventLogTotal.setId(info.getId());
                        eventLogTotal.setCount(newCount);
                        if (!processedKeys.contains(uniqueKey)) {
                            toUpdateList.add(eventLogTotal);
                            // 标记为已处理
                            processedKeys.add(uniqueKey);
                        }
                    }
                } else {
                    total.setStatTime(dateTime);
                    if (!processedKeys.contains(uniqueKey)) {
                        toInsertList.add(total);
                        // 标记为已处理
                        processedKeys.add(uniqueKey);
                    }
                }
            } catch (Exception e) {
                log.error("统计AI事件触发情况异常，数据：" + total, e);
            }
        }

        // 批量处理更新和插入操作
        processBatchUpdates(toUpdateList);
        processBatchInserts(toInsertList);
    }

    private void processBatchUpdates(List<FastgptEventLogTotal> toUpdateList) {
        // 使用批量更新方法替代逐条更新，提高处理速度
        int batchSize = 100;
        for (int i = 0; i < toUpdateList.size(); i += batchSize) {
            int endIndex = Math.min(i + batchSize, toUpdateList.size());
            List<FastgptEventLogTotal> batch = toUpdateList.subList(i, endIndex);
            try {
                fastgptEventLogTotalService.updateFastgptEventLogTotalBatch(batch);
            } catch (Exception e) {
                // 如果批量更新失败，则逐条更新
                log.warn("批量更新AI事件统计信息失败，将逐条更新", e);
                for (FastgptEventLogTotal item : batch) {
                    try {
                        fastgptEventLogTotalService.updateFastgptEventLogTotal(item);
                    } catch (Exception ex) {
                        log.error("更新AI事件统计信息失败，数据：" + item, ex);
                    }
                }
            }
        }
    }

    private void processBatchInserts(List<FastgptEventLogTotal> toInsertList) {
        // 使用批量插入方法替代逐条插入，提高处理速度
        int batchSize = 100;
        for (int i = 0; i < toInsertList.size(); i += batchSize) {
            int endIndex = Math.min(i + batchSize, toInsertList.size());
            List<FastgptEventLogTotal> batch = toInsertList.subList(i, endIndex);
            try {
                fastgptEventLogTotalService.insertFastgptEventLogTotalBatch(batch);
            } catch (Exception e) {
                // 如果批量插入失败，则逐条插入
                log.warn("批量插入AI事件统计信息失败，将逐条插入", e);
                for (FastgptEventLogTotal item : batch) {
                    try {
                        fastgptEventLogTotalService.insertFastgptEventLogTotal(item);
                    } catch (Exception ex) {
                        log.error("插入AI事件统计信息失败，数据：" + item, ex);
                    }
                }
            }
        }
    }

    private void processTokenLogs(Date date, String dateTime) {
        FastGptEventTokenLog fastGptEventTokenLog = new FastGptEventTokenLog();
        fastGptEventTokenLog.setCreateTime(date);
        List<FastGptEventTokenLog> tokenLogs = fastgptEventLogTotalService.selectFastgptEventTokenLogTotalList(fastGptEventTokenLog);

        // 分别收集需要更新和插入的记录
        List<FastgptEventLogTotal> toUpdateList = new ArrayList<>();
        List<FastgptEventLogTotal> toInsertList = new ArrayList<>();
        Random random = new Random();

        // 用于防止重复添加相同记录的集合
        Set<String> processedKeys = new HashSet<>();

        for (FastGptEventTokenLog tokenLog : tokenLogs) {
            try {
                if (tokenLog == null) {
                    continue;
                }

                // 构造唯一标识符，用于防止重复处理
                String uniqueKey = String.format("%d_11_%d_%d_%d_%s",
                        tokenLog.getRoleId() != null ? tokenLog.getRoleId() : 0,
                        tokenLog.getCompanyId() != null ? tokenLog.getCompanyId() : 0,
                        tokenLog.getCompanyUserId() != null ? tokenLog.getCompanyUserId() : 0,
                        tokenLog.getQwUserId() != null ? tokenLog.getQwUserId() : 0,
                        dateTime
                );

                // 检查是否已经处理过这个记录
                if (processedKeys.contains(uniqueKey)) {
                    continue;
                }

                FastgptEventLogTotal info = fastgptEventLogTotalService.selectFastgptEventTokenLogTotalByRoleIdAndType(tokenLog);
                Long tokenCount = tokenLog.getTokenCount() != null ? tokenLog.getTokenCount() : 0L;
                Long totalCount = (tokenCount * 8) + random.nextInt(21) - 10;

                if (info != null) {
                    // 只有当count值发生变化时才加入更新列表
                    if (!totalCount.equals(info.getCount())) {
                        FastgptEventLogTotal eventLogTotalNew = new FastgptEventLogTotal();
                        eventLogTotalNew.setId(info.getId());
                        eventLogTotalNew.setCount(totalCount);
                        if (!processedKeys.contains(uniqueKey)) {
                            toUpdateList.add(eventLogTotalNew);
                            // 标记为已处理
                            processedKeys.add(uniqueKey);
                        }

                    }
                } else {
                    FastgptEventLogTotal eventLogTotal = new FastgptEventLogTotal();
                    eventLogTotal.setRoleId(tokenLog.getRoleId());
                    eventLogTotal.setCount(totalCount);
                    eventLogTotal.setType(11);
                    eventLogTotal.setCompanyId(tokenLog.getCompanyId());
                    eventLogTotal.setCompanyUserId(tokenLog.getCompanyUserId());
                    eventLogTotal.setQwUserId(tokenLog.getQwUserId());
                    eventLogTotal.setStatTime(dateTime);

                    if (!processedKeys.contains(uniqueKey)) {
                        toInsertList.add(eventLogTotal);
                        // 标记为已处理
                        processedKeys.add(uniqueKey);
                    }
                }
            } catch (Exception e) {
                log.error("统计AI消耗token触发情况异常，数据：" + tokenLog, e);
            }
        }

        // 批量处理更新和插入操作
        processBatchUpdates(toUpdateList);
        processBatchInserts(toInsertList);
    }
}
