package com.fs.course.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fs.course.domain.FsUserWatchCourseStatistics;
import com.fs.course.mapper.FsUserCoursePeriodDaysMapper;
import com.fs.course.mapper.FsUserWatchCourseStatisticsMapper;
import com.fs.course.service.IFsUserWatchCourseStatisticsService;
import com.fs.his.mapper.FsUserMapper;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 会员看课统计-按课程统计Service业务层处理
 *
 * @author fs
 * @date 2025-06-17
 */
@Service
@AllArgsConstructor
@Slf4j
public class FsUserWatchCourseStatisticsServiceImpl extends ServiceImpl<FsUserWatchCourseStatisticsMapper, FsUserWatchCourseStatistics> implements IFsUserWatchCourseStatisticsService {

    private FsUserCoursePeriodDaysMapper fsUserCoursePeriodDaysMapper;

    private FsUserMapper fsUserMapper;

    @Autowired
    private SqlSessionFactory sqlSessionFactory;

    /**
     * 查询会员看课统计-按课程统计
     *
     * @param id 会员看课统计-按课程统计主键
     * @return 会员看课统计-按课程统计
     */
    @Override
    public FsUserWatchCourseStatistics selectFsUserWatchCourseStatisticsById(Long id)
    {
        return baseMapper.selectFsUserWatchCourseStatisticsById(id);
    }

    /**
     * 查询会员看课统计-按课程统计列表
     *
     * @param fsUserWatchCourseStatistics 会员看课统计-按课程统计
     * @return 会员看课统计-按课程统计
     */
    @Override
    public List<FsUserWatchCourseStatistics> selectFsUserWatchCourseStatisticsList(FsUserWatchCourseStatistics fsUserWatchCourseStatistics)
    {
        List<FsUserWatchCourseStatistics> list = baseMapper.selectFsUserWatchCourseStatisticsList(fsUserWatchCourseStatistics);
        if(!list.isEmpty()){
            for (FsUserWatchCourseStatistics userWatchCourseStatistics : list) {
                userWatchCourseStatistics.setCompleteWatchRatePercent(userWatchCourseStatistics.getCompleteWatchRate() + "%");
                userWatchCourseStatistics.setAnswerRightRatePercent(userWatchCourseStatistics.getAnswerRightRate() + "%");
                userWatchCourseStatistics.setOnlineRatePercent(userWatchCourseStatistics.getOnlineRate() + "%");
            }
        }
        return list;
    }

    @Override
    public List<FsUserWatchCourseStatistics> selectFsUserWatchCourseStatisticsListTotal(FsUserWatchCourseStatistics fsUserWatchCourseStatistics)
    {
        return baseMapper.selectFsUserWatchCourseStatisticsListTotal(fsUserWatchCourseStatistics);
    }

    /**
     * 新增会员看课统计-按课程统计
     *
     * @param fsUserWatchCourseStatistics 会员看课统计-按课程统计
     * @return 结果
     */
    @Override
    public int insertFsUserWatchCourseStatistics(FsUserWatchCourseStatistics fsUserWatchCourseStatistics)
    {
        return baseMapper.insertFsUserWatchCourseStatistics(fsUserWatchCourseStatistics);
    }

    /**
     * 修改会员看课统计-按课程统计
     *
     * @param fsUserWatchCourseStatistics 会员看课统计-按课程统计
     * @return 结果
     */
    @Override
    public int updateFsUserWatchCourseStatistics(FsUserWatchCourseStatistics fsUserWatchCourseStatistics)
    {
        return baseMapper.updateFsUserWatchCourseStatistics(fsUserWatchCourseStatistics);
    }

    /**
     * 批量删除会员看课统计-按课程统计
     *
     * @param ids 需要删除的会员看课统计-按课程统计主键
     * @return 结果
     */
    @Override
    public int deleteFsUserWatchCourseStatisticsByIds(Long[] ids)
    {
        return baseMapper.deleteFsUserWatchCourseStatisticsByIds(ids);
    }

    /**
     * 删除会员看课统计-按课程统计信息
     *
     * @param id 会员看课统计-按课程统计主键
     * @return 结果
     */
    @Override
    public int deleteFsUserWatchCourseStatisticsById(Long id)
    {
        return baseMapper.deleteFsUserWatchCourseStatisticsById(id);
    }

    @Override
    public void insertWatchCourseStatistics() {
        // 1、获取统计数据
        // 查询课程相关数据
        try{
            List<FsUserWatchCourseStatistics> fsUserWatchCourseStatistics = fsUserCoursePeriodDaysMapper.selectDaysCountList();

            // 查询统计数据
            List<FsUserWatchCourseStatistics> watchLog = fsUserMapper.selectWatchLogCount();
            List<FsUserWatchCourseStatistics> redPacketLog = fsUserMapper.selectRedPacketLogCount();
            List<FsUserWatchCourseStatistics> answerLog = fsUserMapper.selectAnswerLogCount();
            List<FsUserWatchCourseStatistics> userTotal = fsUserMapper.selectFsUserDetail();

            // 转化为自定义键的map
            Map<String, FsUserWatchCourseStatistics> watchLogMap = watchLog.stream().collect(Collectors.toMap(k -> String.format("%s-%s-%s", k.getPeriodId(), k.getVideoId(), k.getCompanyUserId()), v -> v));
            Map<String, FsUserWatchCourseStatistics> redPacketLogMap = redPacketLog.stream().collect(Collectors.toMap(k -> String.format("%s-%s-%s", k.getPeriodId(), k.getVideoId(), k.getCompanyUserId()), v -> v));
            Map<String, FsUserWatchCourseStatistics> answerLogMap = answerLog.stream().collect(Collectors.toMap(k -> String.format("%s-%s-%s", k.getPeriodId(), k.getVideoId(), k.getCompanyUserId()), v -> v));
            Map<Long, List<FsUserWatchCourseStatistics>> userTotalMap = userTotal.stream()
                    .collect(Collectors.groupingBy(FsUserWatchCourseStatistics::getCompanyUserId));

            // 处理数据
            List<FsUserWatchCourseStatistics> list = new ArrayList<>();
            for (FsUserWatchCourseStatistics data : fsUserWatchCourseStatistics) {
                FsUserWatchCourseStatistics vo = new FsUserWatchCourseStatistics();
                String key = String.format("%s-%s-%s", data.getPeriodId(), data.getVideoId(), data.getCompanyUserId());
                FsUserWatchCourseStatistics watchLogData = watchLogMap.get(key);
                FsUserWatchCourseStatistics redPacketLogData = redPacketLogMap.get(key);
                FsUserWatchCourseStatistics answerLogData = answerLogMap.get(key);
                List<FsUserWatchCourseStatistics> userTotalDataList = userTotalMap.get(data.getCompanyUserId());
                BeanUtils.copyProperties(data, vo);
                // 改成使用营期线来表示营期开始时间
                vo.setPeriodStartingTime(data.getPeriodLine() != null ? data.getPeriodLine() : data.getPeriodStartingTime());

                // 单独一个一个set，不用copy，避免copy出来的结果被前面的覆盖
                if(userTotalDataList != null && !userTotalDataList.isEmpty()){
                    // 获取过滤时间后的销售会员数量
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");

//                    int userNum = userTotalDataList.stream()
//                            .filter(v -> v.getUserCreateDate().before(data.getCourseStartDateTime())).mapToInt(FsUserWatchCourseStatistics::getUserNum).sum();
//                    int newUserNum = userTotalDataList.stream()
//                            .filter(v -> sdf.format(v.getUserCreateDate()).equals(sdf.format(data.getCourseStartDateTime()))).mapToInt(FsUserWatchCourseStatistics::getUserNum).sum();
                    int userNum = userTotalDataList.stream()
                            .filter(v -> {
                                if (v.getUserCreateDate() == null || data.getCourseStartDateTime() == null || v.getUserNum() == null){
                                    return false;
                                }
                                return v.getUserCreateDate().before(data.getCourseStartDateTime());
                            }).mapToInt(FsUserWatchCourseStatistics::getUserNum).sum();
                    int newUserNum = userTotalDataList.stream()
                            .filter(v -> {
                                if (v.getUserCreateDate() == null || data.getCourseStartDateTime() == null || v.getUserNum() == null){
                                    return false;
                                }
                                return sdf.format(v.getUserCreateDate()).equals(sdf.format(data.getCourseStartDateTime()));
                            }).mapToInt(FsUserWatchCourseStatistics::getUserNum).sum();
                    vo.setUserNum(userNum);
                    vo.setNewUserNum(newUserNum);
                } else {
                    vo.setUserNum(0);
                    vo.setNewUserNum(0);
                }

                if(watchLogData != null) {
                    vo.setWatchNum(watchLogData.getWatchNum());
                    vo.setCompleteWatchNum(watchLogData.getCompleteWatchNum());
                    vo.setCompleteWatchRate(watchLogData.getCompleteWatchRate());
                } else {

                    vo.setWatchNum(0);
                    vo.setCompleteWatchNum(0);
                    vo.setCompleteWatchRate(BigDecimal.ZERO);
                }

                if(redPacketLogData != null) {
                    vo.setRedPacketNum(redPacketLogData.getRedPacketNum());
                    vo.setRedPacketAmount(redPacketLogData.getRedPacketAmount());
                } else {
                    vo.setRedPacketNum(0);
                    vo.setRedPacketAmount(BigDecimal.ZERO);
                }

                if(answerLogData != null) {
                    vo.setAnswerNum(answerLogData.getAnswerNum());
                    vo.setAnswerRightNum(answerLogData.getAnswerRightNum());
                    vo.setAnswerRightRate(answerLogData.getAnswerRightRate());
                } else {
                    vo.setAnswerNum(0);
                    vo.setAnswerRightNum(0);
                    vo.setAnswerRightRate(BigDecimal.ZERO);
                }

                // 设置上线率
                BigDecimal watchNum = new BigDecimal(vo.getWatchNum());
                BigDecimal userNum = new BigDecimal(vo.getUserNum());
                if(!userNum.equals(BigDecimal.ZERO)){
                    BigDecimal onlineRate = watchNum.divide(userNum, 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
                    vo.setOnlineRate(onlineRate);
                } else{
                    vo.setOnlineRate(BigDecimal.ZERO);
                }

                vo.setCreateTime(new Date());
                vo.setUpdateTime(new Date());
                list.add(vo);
            }

            //2、分批次插入数据
            this.batchInsert(list);
        }catch (Exception e){
            e.printStackTrace();
            log.error("数据存在问题：{}",e.getMessage());
        }

    }

    private void batchInsert(List<FsUserWatchCourseStatistics> list) {
        // 分批次处理，一次提交500条
        List<List<FsUserWatchCourseStatistics>> batches = Lists.partition(list, 500);
        batches.forEach(batch -> {
            SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
            try {
                FsUserWatchCourseStatisticsMapper mapper = sqlSession.getMapper(FsUserWatchCourseStatisticsMapper.class);
                batch.forEach(mapper::insertFsUserWatchCourseStatisticsTask);
                sqlSession.commit();
            } finally {
                sqlSession.close();
            }
        });
    }

}
