package com.fs.course.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fs.company.domain.Company;
import com.fs.company.mapper.CompanyMapper;
import com.fs.course.domain.FsUserCoursePeriod;
import com.fs.course.domain.FsUserWatchStatistics;
import com.fs.course.mapper.FsUserCoursePeriodMapper;
import com.fs.course.mapper.FsUserWatchStatisticsMapper;
import com.fs.course.service.IFsUserWatchStatisticsService;
import com.fs.his.mapper.FsUserMapper;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
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 org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 会员看课统计-按营期统计Service业务层处理
 *
 * @author fs
 * @date 2025-06-16
 */
@Service
@AllArgsConstructor
public class FsUserWatchStatisticsServiceImpl extends ServiceImpl<FsUserWatchStatisticsMapper, FsUserWatchStatistics> implements IFsUserWatchStatisticsService {

    private final FsUserCoursePeriodMapper fsUserCoursePeriodMapper;

    private final FsUserMapper fsUserMapper;

    @Autowired
    private SqlSessionFactory sqlSessionFactory;

    private final CompanyMapper companyMapper;

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

    /**
     * 查询会员看课统计-按营期统计列表
     *
     * @param fsUserWatchStatistics 会员看课统计-按营期统计
     * @return 会员看课统计-按营期统计
     */
    @Override
    public List<FsUserWatchStatistics> selectFsUserWatchStatisticsList(FsUserWatchStatistics fsUserWatchStatistics)
    {
        return baseMapper.selectFsUserWatchStatisticsList(fsUserWatchStatistics);
    }

    /**
     * 新增会员看课统计-按营期统计
     *
     * @param fsUserWatchStatistics 会员看课统计-按营期统计
     * @return 结果
     */
    @Override
    public int insertFsUserWatchStatistics(FsUserWatchStatistics fsUserWatchStatistics)
    {
        return baseMapper.insertFsUserWatchStatistics(fsUserWatchStatistics);
    }

    /**
     * 修改会员看课统计-按营期统计
     *
     * @param fsUserWatchStatistics 会员看课统计-按营期统计
     * @return 结果
     */
    @Override
    public int updateFsUserWatchStatistics(FsUserWatchStatistics fsUserWatchStatistics)
    {
        return baseMapper.updateFsUserWatchStatistics(fsUserWatchStatistics);
    }

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

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

    @Override
    @Transactional
    public void insertStatistics() {
        // 1、获取统计结果
        // 获取所有的营期，并拆分公司id
        FsUserCoursePeriod periodParam = new FsUserCoursePeriod();
        List<FsUserCoursePeriod> fsUserCoursePeriods = fsUserCoursePeriodMapper.selectFsUserCoursePeriodList(periodParam);
        Set<Long> companyIds = fsUserCoursePeriods.stream()
                .flatMap(item -> Arrays.stream(item.getCompanyId().split(",")))
                .map(Long::valueOf)
                .collect(Collectors.toSet());

        // 获取公司信息
        List<Company> companies = companyMapper.selectCompanyByIds2(companyIds);
        Map<Long, Company> companyMap = companies.stream().collect(Collectors.toMap(Company::getCompanyId, Function.identity()));

        // 获取看课统计（按营期按公司）
        List<FsUserWatchStatistics> courseWatchStatistics = baseMapper.getCourseWatchStatistics();
        Map<String, FsUserWatchStatistics> courseWatchStatisticsMap = courseWatchStatistics.stream().collect(Collectors.toMap(k -> String.format("%s-%s", k.getPeriodId(), k.getCompanyId()), v -> v));

        //获取公司的会员数量和今日新增会员数量
        List<FsUserWatchStatistics> userTotal = fsUserMapper.selectFsUserTotal();
        Map<String, FsUserWatchStatistics> userTotalMap;
        if (userTotal != null && !userTotal.isEmpty()) {
            userTotalMap = userTotal.stream().collect(Collectors.toMap(FsUserWatchStatistics::getCompanyId, Function.identity()));
        } else {
            userTotalMap = null;
        }
        if (!fsUserCoursePeriods.isEmpty()) {
            List<FsUserWatchStatistics> list = fsUserCoursePeriods.stream()
                    .flatMap(item -> Arrays.stream(item.getCompanyId().split(","))
                            .map(companyIdStr -> {
                                Long companyId = Long.valueOf(companyIdStr.trim());
                                Company company = companyMap.get(companyId);

                                // 赋值
                                FsUserWatchStatistics fsUserWatchStatistics = new FsUserWatchStatistics();
                                BeanUtils.copyProperties(item, fsUserWatchStatistics);
                                ZonedDateTime zonedDateTime = item.getPeriodStartingTime().atStartOfDay(ZoneId.systemDefault());
                                // 改成使用营期线来表示营期开始时间
                                fsUserWatchStatistics.setPeriodStartingTime(item.getPeriodLine() != null ? item.getPeriodLine() : Date.from(zonedDateTime.toInstant()));
                                fsUserWatchStatistics.setCompanyId(companyIdStr.trim());
                                fsUserWatchStatistics.setCompanyName(company != null ? company.getCompanyName() : null);
                                if (Objects.nonNull(userTotalMap)){
                                    FsUserWatchStatistics userTotalData = userTotalMap.get(fsUserWatchStatistics.getCompanyId());
                                    if(userTotalData != null){
                                        fsUserWatchStatistics.setUserNum(userTotalData.getUserNum());
                                        fsUserWatchStatistics.setNewUserNum(userTotalData.getNewUserNum());
                                    } else {
                                        fsUserWatchStatistics.setUserNum(0);
                                        fsUserWatchStatistics.setNewUserNum(0);
                                    }
                                }

                                String key = String.format("%s-%s", fsUserWatchStatistics.getPeriodId(), fsUserWatchStatistics.getCompanyId());
                                FsUserWatchStatistics watchData = courseWatchStatisticsMap.get(key);



                                if(watchData != null){
                                    fsUserWatchStatistics.setWatchNum(watchData.getWatchNum());
                                    fsUserWatchStatistics.setCompleteWatchNum(watchData.getCompleteWatchNum());
                                    fsUserWatchStatistics.setCompleteWatchRate(watchData.getCompleteWatchRate());
                                } else {
                                    fsUserWatchStatistics.setWatchNum(0);
                                    fsUserWatchStatistics.setCompleteWatchNum(0);
                                    fsUserWatchStatistics.setCompleteWatchRate(BigDecimal.ZERO);
                                }

                                // 计算上线率
                                BigDecimal watchNum = new BigDecimal(fsUserWatchStatistics.getWatchNum());
                                BigDecimal userNum = new BigDecimal(fsUserWatchStatistics.getUserNum());
                                if(!userNum.equals(BigDecimal.ZERO)){
                                    BigDecimal onlineRate = watchNum.divide(userNum, 2, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
                                    fsUserWatchStatistics.setOnlineRate(onlineRate);
                                } else {
                                    fsUserWatchStatistics.setOnlineRate(BigDecimal.ZERO);
                                }

                                fsUserWatchStatistics.setCreateTime(new Date());
                                fsUserWatchStatistics.setUpdateTime(new Date());
                                return fsUserWatchStatistics;
                            })).collect(Collectors.toList());
            //2、分批次插入数据
            this.batchInsert(list);
        }


    }

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