package com.cirle.scientific.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.cirle.scientific.constants.PlayRecordLogConstants;
import com.cirle.scientific.dao.*;
import com.cirle.scientific.dto.QkjTqcourseCourseDto;
import com.cirle.scientific.dto.QkjTqcourseDto;
import com.cirle.scientific.po.*;
import com.cirle.scientific.pojo.BizCodeEnum;
import com.cirle.scientific.pojo.Result;
import com.cirle.scientific.service.CommonService;
import com.cirle.scientific.service.CourseService;
import com.cirle.scientific.service.OrderService;
import com.cirle.scientific.service.QkjTaskService;
import com.cirle.scientific.utils.CopyUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.thymeleaf.util.ListUtils;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 留言：
 * 大家写代码的时候尽量不要一个方法写几百上千行哦，我们不是写PHP的哈
 *
 * 如果不是很清除如何拆分、封装、复用方法，这里有个简单的办法，比如一个大的业务执行，不要全部写到
 * 一个方法里面，把大业务流程拆分成一个个的原子性功能的方法，然后将不同的方法组合起来实现最终的结果。
 *
 * 希望大家至少能给方法加一个注释哦，哪怕一个很简单的描述就很好呢，比如【首页数据查询】
 *
 * Oracle代码规范建议，在确保代码不丢失安全性的情况下尽可能写出更加易读的代码。大佬们都喜欢秀技术和
 * 新语法，但别丢了可读性哦。要做一枚令人赞同的程序员呐~ 会不会新语法没那么重要，尽管是初学者，写的代
 * 码不是很好，只要代码规范，必要的注释齐全，后面维护的人看到也会很尊重和敬畏这个开发者的。
 * <p>
 * 还有就是，大家写代码的时候，尽量控制缩进不要超过3层呐。if嵌套的时候，尽量将自己的代码执行流程改为线
 * 性执行，而不是自由的分叉很多个。什么是线性执行呐，就是你的代码从进入代码体第一行开始，围绕完整正确的
 * 业务流程去执行，如果遇到非法（即不合理，无法为其处理）的情况使用return、throw等方式给出友好的异常
 * 提示并终止其后续执行，方法只有一条正常的线路从第一行执行到末尾。如(当然，这些只是伪代码)：
 * <p>
 * // 推荐方式
 * public void sendEmail(String emailAddress, String emailText) throw EmailSendingException {
 * // 校验邮箱地址是否正确（比如这里将对邮箱地址检查的逻辑抽出来，而不是直接在这里写一堆逻辑）
 * if (!validator.isLegalEmail(emailAddress)) throw new EmailSendingException("地址不合法");
 * <p>
 * // 校验邮件内容是否为空
 * if (StringUtils.isBlank(emailText)) throw new EmailSendingException("邮件内容不能为空");
 * <p>
 * // 校验邮件内容是否合法
 * // 这种简单的检查就不用抽成方法啦，如果后续需求变更导致这里代码量变多，请抽离为单独的校验方法
 * // 10000这个值能定义为一个MAX_EMAIL_CONTENT_LENGTH就更棒啦
 * if (emailText.length() > 10000) throw new EmailSendingException("邮件内容过长");
 * <p>
 * // 构建客户端
 * EmailClient emailClient = new QQEmailClient();
 * emailClient.setReceiver(emailAddress);
 * emailClient.setContent(emailText);
 * try {
 * // 发送邮件
 * emailClient.sent();
 * } catch (Exception e) {
 * // 当一个方法封装了别的许多方法调用时，难免会遇到各种异常处理，如网络异常、QQ邮箱服务器异常等等。
 * // 建议将该方法种所有异常转换为邮件发送异常（EmailSendingException），但注意将异常堆栈信息传
 * // 递下去，因为我们只是这个异常链种中的一个环节。直到该处理的异常的地方再进行异常处理，比如最终
 * // Controller将该异常捕获，并进行处理（即向前端响应友好的异常说明信息）。
 * throw new EmailSendingException(e);
 * }
 * }
 * <p>
 * // 不推荐方式
 * public Map<String, String> sendEmail(String emailAddress, String emailText) {
 * <p>
 * Map<String, String> result = new HashMap<>();
 * <p>
 * if (validator.isLegalEmail(emailAddress)) {
 * if (StringUtils.isNotBlank(emailText)) {
 * if (emailText.length() < 10000) {
 * EmailClient emailClient = new QQEmailClient();
 * emailClient.setReceiver(emailAddress);
 * emailClient.setContent(emailText);
 * try {
 * emailClient.sent();
 * result.put("msg", "发送成功");
 * return result;
 * } catch (Exception e) {
 * result.put("msg", "发送失败");
 * return result;
 * }
 * } else {
 * result.put("msg", "邮件内容过长");
 * return result;
 * }
 * } else {
 * result.put("msg", "邮件内容不能为空");
 * return result;
 * }
 * } else {
 * result.put("msg", "地址不合法");
 * return result;
 * }
 * }
 * <p>
 * 对于日后可能造成影响、或因为赶时间代码实现不严谨可能存在bug、或日后需要优化的地方可以用TODO: 加一句简单的说明
 * <p>
 * 代码中的警告大家多少留意一下，很多都是些能顺手就避免的事儿哈，比如没用到的导包，没用到的注入bean。这个将来也是
 * 对自己代码规范的一种提升 ＜（＾－＾）＞
 * <p>
 * ====================留言完====================
 * <p>
 * TODO: 该类中所有【】引起来的话日后请移除
 * TODO: 该类中添加的所有注释都是我个人理解和猜测的，不一定正确
 */
@Service
@Transactional
@Slf4j
public class CourseServiceImpl implements CourseService {


    @Autowired
    QkjTqcourseDao qkjTqcourseDao;
    @Autowired
    QkjZqTqcourseDetailDao qkjZqTqcourseDetailDao;
    @Autowired
    QkjTqcourseCourseDao qkjTqcourseCourseDao;
    @Autowired
    QkjTagsDao qkjTagsDao;
    @Autowired
    QkjTagsDetailDao qkjTagsDetailDao;
    @Autowired
    QkjVodinfoDao qkjVodinfoDao;
    @Autowired
    QkjCatalogsDetailDao qkjCatalogsDetailDao;
    @Autowired
    QkjTqcourseCommentsDao qkjTqcourseCommentsDao;
    @Autowired
    OrderDao orderDao;

    @Autowired
    QkjCatalogsDao qkjCatalogsDao;

    @Autowired
    QkjVedioPlayRecordDao qkjVedioPlayRecordDao;

    @Autowired
    QkjVideoPlayLogDao qkjVideoPlayLogDao;


    @Autowired
    QkjVedioPlayRecordLogDao qkjVedioPlayRecordLogDao;

    @Autowired
    QkjMemberTaskInfoDao qkjMemberTaskInfoDao;
    @Autowired
    QkjColumnistDetailDao qkjColumnistDetailDao;
    @Autowired
    QkjColumnistDao qkjColumnistDao;
    @Autowired
    QkjTaskService taskService;
    @Autowired
    CollectionDao collectionDao;
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    private CommonService commonService;
    @Autowired
    private MemberDao memberDao;
    @Autowired
    private OrderService orderService;

    @Autowired
    private QkjLiveDao qkjLiveDao;


    /**
     * 获取首页数据 【这里一句话简介这个方法是做什么的】
     * <p>
     * 该方法提供用于首页展示的数据（包括WEB和H5） 【可选部分，如有不要添加该部分进行说明，特别是容易产生疑问的地方，您十分简单的几个字即可帮助阅读者节省大量时间】
     *
     * @param cataId
     * @param fId
     * @param start
     * @param size    分页大小 【我不确定】
     * @param memCard
     * @param sortBy  排序
     * @param from
     * @return
     */
    @Override
    public Result getIndexData(Integer cataId, Integer fId, Integer start, Integer size, String memCard, String sortBy, String from, boolean isPC) {
        Integer[] mOrPc = new Integer[2];//电脑
        if (isPC) { //手机
            mOrPc[0] = 0;
            mOrPc[1] = 2;
        } else {
            mOrPc[0] = 1;
            mOrPc[1] = 2;
        }

        /*
         * 分页总条数
         *
         * 该变量仅作用于PC页面（即WEB页），因为只有PC端才采用分页方式，H5界面采用动态加载方式，故不需要。
         */
        Integer total = 0;
        if (fId == null) {
            fId = -1;
        }
        if (cataId == null) {
            cataId = -1;
        }

        if (cataId == -1) {
            //查询全部课程
            if (fId == -1) {
                //查询首页数据列表
                List<QkjTqcourse> data = new ArrayList<>();
                total = qkjTqcourseDao.getIndexDataCounts(mOrPc);

                if ("H5".equals(from)){
                    //根据后台设置sortNum 排序
                    data = qkjTqcourseDao.getIndexDataBysortNum((start - 1) * size, size, mOrPc);
                }else {

                    if ("hottest".equals(sortBy)){
                        //最热数据
                        data = qkjTqcourseDao.getIndexHottestData((start - 1) * size, size, mOrPc);
                    }else {
                        //最新数据
                        data = qkjTqcourseDao.getIndexNewestData((start - 1) * size, size, mOrPc);
                    }
                }

                List<QkjTqcourseDto> coll = data.stream().map(item -> {
                    QkjTqcourseDto qkjTqcourseDto = CopyUtil.copy(item, QkjTqcourseDto.class);
                    qkjTqcourseDto.setStudyNumTOW(qkjTqcourseDto.getPurchasedMembers()+qkjTqcourseDto.getStudyNum());
                    List<SalesOrdersMain> tqcourseOrderList = orderDao.findTqcourseOrderList(memCard, 1, item.getId().intValue());
                    if (tqcourseOrderList != null && !tqcourseOrderList.isEmpty()) {
                        qkjTqcourseDto.setIsBuy(1);
                    } else {
                        qkjTqcourseDto.setIsBuy(0);
                    }
                    Integer IsBuy = judgeIsBuy(memCard, item.getId());
                    if(IsBuy == 1){
                        qkjTqcourseDto.setIsBuy(IsBuy);
                    }
                    Integer purchasedMembers = 0;
                    Integer purchasedMembersTOW = 0;
                    //如果是专区的话,就算出子课程的所有的学习人数
                    if (qkjTqcourseDto.getZq() == 2) {
                        List<QkjTqcourse> list = qkjTqcourseDao.findTqListForZq(qkjTqcourseDto.getId().intValue());
                        if (list != null && !list.isEmpty()) {
                            for (QkjTqcourse q : list) {
                                if (q.getPurchasedMembers() != null) {
                                    purchasedMembers = purchasedMembers + q.getPurchasedMembers();
                                    purchasedMembersTOW = purchasedMembersTOW + q.getPurchasedMembers() + q.getStudyNum();
                                }
                            }
                            qkjTqcourseDto.setTotalClassHours(list.size());
                            qkjTqcourseDto.setPurchasedMembers(purchasedMembers);
                            qkjTqcourseDto.setStudyNumTOW(purchasedMembersTOW);
                        }
                    }
                    return qkjTqcourseDto;
                }).collect(Collectors.toList());
                if (coll != null && !coll.isEmpty()) {
                    if ("web".equals(from)) {
                        Map<String, Object> results = new HashMap<>();
                        results.put("results", coll);
                        results.put("total", total);
                        return Result.success(results);
                    }
                    return Result.success(coll);
                }
            } else {
                //查询子课数据列表  没有分类
                QkjTqcourse qkjTqcourse = qkjTqcourseDao.findById(fId.longValue()).get();

                /*
                 * 需求：【学习人数，要求按照浏览记录计算，只要点击进去，就算一次】
                 * 详情：https://docs.qq.com/sheet/DQ2tHSGxSU0ZMdm9l?u=560d32cc53624094bc53c60768480dca&tab=ptb1hr&viewId=vfj394
                 */
                studyCountPlus1(qkjTqcourse);

                qkjTqcourse.setSharePic(commonService.buildImgUrl(qkjTqcourse.getSharePic()));
                Long zqId = qkjTqcourse.getId();
                JSONObject data = new JSONObject();
                if (qkjTqcourse != null && qkjTqcourse.getZq() == 1) {
                    //普通课时 查询qkj_tqcourse_course表
                    List<QkjTqcourseCourse> qkjTqcourseCourses = qkjTqcourseCourseDao.findCourseCourse(zqId.intValue());
                    if (qkjTqcourseCourses != null && !qkjTqcourseCourses.isEmpty()) {
                        List<QkjTqcourseCourseDto> list = qkjTqcourseCourses.stream().map(item -> {
                            QkjTqcourseCourseDto dto = CopyUtil.copy(item, QkjTqcourseCourseDto.class);
                            //将主课的是否问卷赋值给子课
                            dto.setQuestionFlag(qkjTqcourse.getQuestionFlag() == null ? 0 : qkjTqcourse.getQuestionFlag());
                            //如果当前子课没有选则是否为定向课程，则判断课程所属专区是否为定向人员课程专区
                            if (!Integer.valueOf(1).equals(qkjTqcourse.getIsSpecialCourse())) {
                                List<QkjTqcourse> tqListForZqs = qkjTqcourseDao.findTqListFortqId(qkjTqcourse.getId().intValue());
                                if (tqListForZqs != null && !tqListForZqs.isEmpty()) {
                                    for (QkjTqcourse q : tqListForZqs) {
                                        if (q.getIsSpecialCourse() != null && "1".equals(q.getIsSpecialCourse().toString())) {
                                            dto.setIsSpecialCourse(q.getIsSpecialCourse());
                                            break;
                                        }
                                    }
                                }
                            } else {
                                dto.setIsSpecialCourse(qkjTqcourse.getIsSpecialCourse() == null ? 0 : qkjTqcourse.getIsSpecialCourse());
                            }
                            //查询作者
                            List<QkjColumnistDetail> byobjTypeAndobjIdAuthor = qkjColumnistDetailDao.findByobjTypeAndobjIdAuthor(1, item.getId().intValue());
                            if (byobjTypeAndobjIdAuthor != null && !byobjTypeAndobjIdAuthor.isEmpty()) {
                                QkjColumnistDetail qkjColumnistDetail = byobjTypeAndobjIdAuthor.get(0);
                                QkjColumnist byMemCard = qkjColumnistDao.findByMemCard(qkjColumnistDetail.getMemCard());
                                dto.setAuthor(byMemCard.getMemUsername());
                                dto.setProfessional(byMemCard.getMemTitle());
                            }
                            //查询标签
                            List<QkjTags> tags = qkjTagsDao.findCourseTagsByCourseId(item.getId());
                            dto.setTags(tags);
                            //查询视频信息
                            Optional<QkjVodinfo> byId = qkjVodinfoDao.findById(item.getVodId().longValue());
                            if (byId.isPresent()) {
                                QkjVodinfo qkjVodinfo = byId.get();
                                dto.setQkjVodinfo(qkjVodinfo);
                            }
                            return dto;
                        }).collect(Collectors.toList());
                        data.put("list", list);
                    } else {
                        if (!Integer.valueOf(1).equals(qkjTqcourse.getIsSpecialCourse())) {
                            List<QkjTqcourse> tqListForZqs = qkjTqcourseDao.findTqListFortqId(qkjTqcourse.getId().intValue());
                            if (tqListForZqs != null && !tqListForZqs.isEmpty()) {
                                for (QkjTqcourse q : tqListForZqs) {
                                    if (q.getPurchasedMembers() != null) {
                                        if (Integer.valueOf(1).equals(q.getIsSpecialCourse())) {
                                            qkjTqcourse.setIsSpecialCourse(q.getIsSpecialCourse());
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    QkjTqcourseDto qkjTqcourseDto = CopyUtil.copy(qkjTqcourse, QkjTqcourseDto.class);
                    //查询是否购买
                    List<SalesOrdersMain> tqcourseOrderList = orderDao.findTqcourseOrderList(memCard, 1, qkjTqcourse.getId().intValue());
                    if (tqcourseOrderList != null && !tqcourseOrderList.isEmpty()) {
                        if (StringUtils.isNotBlank(memCard) && judgeCoursePurchased(qkjTqcourse, memCard)) {
                            qkjTqcourseDto.setIsBuy(1);
                        } else {
                            qkjTqcourseDto.setIsBuy(0);
                        }
                    }
                    Integer IsBuy = judgeIsBuy(memCard,qkjTqcourse.getId());
                    if(IsBuy == 1){
                        qkjTqcourseDto.setIsBuy(IsBuy);
                    }
                    Integer purchasedMembers1 = 0;
                    if (qkjTqcourseDto.getZq() == 2) {
                        List<QkjTqcourse> list = qkjTqcourseDao.findTqListForZq(qkjTqcourseDto.getId().intValue());
                        if (list != null && !list.isEmpty()) {
                            for (QkjTqcourse q : list) {
                                if (q.getPurchasedMembers() != null) {
                                    purchasedMembers1 = purchasedMembers1 + q.getPurchasedMembers();
                                }
                            }
                            qkjTqcourseDto.setPurchasedMembers(purchasedMembers1);
                        }
                    }
                    qkjTqcourseDto.setIsController(1);
                    List<SalesCollectionMain> salesCollectionMainList = collectionDao.getCollectionInfo(memCard, qkjTqcourseDto.getId() + "", 1);
                    if (salesCollectionMainList != null & salesCollectionMainList.size() > 0) {
                        qkjTqcourseDto.setIsController(0);
                    }
                    qkjTqcourseDto.setStudyNumTOW(qkjTqcourseDto.getPurchasedMembers()+qkjTqcourseDto.getStudyNum());
                    data.put("info", qkjTqcourseDto);
                    //查询相关课程
                    //查询本课相关的标签
                    String tagIds1 = qkjTqcourse.getTagIds();
                    log.info("tagIds1======" + tagIds1);
                    if (StringUtils.isNotBlank(tagIds1)) {
                        String id = tagIds1.split(",")[0];
                        List<QkjTqcourse> tqListByTagIds = qkjTqcourseDao.findTqListByTagIds(id, qkjTqcourse.getId());
                        List<QkjTqcourseDto> coll = tqListByTagIds.stream().map(item -> {
                            QkjTqcourseDto qkjTqcourseDto1 = CopyUtil.copy(item, QkjTqcourseDto.class);
                            if (StringUtils.isNotBlank(memCard) && judgeCoursePurchased(item, memCard)) {
                                qkjTqcourseDto1.setIsBuy(1);
                            } else {
                                qkjTqcourseDto1.setIsBuy(0);
                            }
                            Integer purchasedMembers = 0;
                            Integer purchasedMembersTOW = 0;
                            if (qkjTqcourseDto1.getZq() == 2) {
                                List<QkjTqcourse> list = qkjTqcourseDao.findTqListForZq(qkjTqcourseDto1.getId().intValue());
                                if (list != null && !list.isEmpty()) {
                                    for (QkjTqcourse q : list) {
                                        if (q.getPurchasedMembers() != null) {
                                            purchasedMembers = purchasedMembers + q.getPurchasedMembers();
                                            purchasedMembersTOW = purchasedMembersTOW + q.getPurchasedMembers()+q.getStudyNum();
                                        }

                                    }
                                    qkjTqcourseDto1.setPurchasedMembers(purchasedMembers);
                                    qkjTqcourseDto1.setStudyNumTOW(purchasedMembersTOW);
                                }
                            }
                            return qkjTqcourseDto1;
                        }).collect(Collectors.toList());
                        data.put("cataList", coll);
                    }
                    //查询课程互动
                    List<QkjTqcourseComments> comments = qkjTqcourseCommentsDao.findCommentsByCourseId(qkjTqcourse.getId());
                    if (comments != null && !comments.isEmpty()) {
                        data.put("comments", comments);
                    }

                    if ("web".equals(from)) {
                        Map<String, Object> results = new HashMap<>();
                        results.put("results", data);
                        results.put("total", total);
                        return Result.success(results);
                    }
                    return Result.success(data);
                } else {

                    QkjTqcourse qkjTqcoursezQ = qkjTqcourseDao.findById(zqId).get();
                    //专区 查询qkj_tqcourse
                    List<QkjTqcourse> list = qkjTqcourseDao.findTqListForZq1(zqId.intValue(), (start - 1) * size, size);
                    List<QkjTqcourseDto> coll = list.stream().map(item -> {
                        QkjTqcourseDto qkjTqcourseDto = CopyUtil.copy(item, QkjTqcourseDto.class);
                        qkjTqcourseDto.setStudyNumTOW(qkjTqcourseDto.getPurchasedMembers()+qkjTqcourseDto.getStudyNum());
                        //如果当前课程没有选则是否为定向课程，则判断课程所属专区是否为定向人员课程专区
                        if (!Integer.valueOf(1).equals(qkjTqcourseDto.getIsSpecialCourse())) {
                            qkjTqcourseDto.setIsSpecialCourse(qkjTqcoursezQ.getIsSpecialCourse() == null ? 0 : qkjTqcoursezQ.getIsSpecialCourse());
                        }
                        if (StringUtils.isNotBlank(memCard) && judgeCoursePurchased(qkjTqcourse, memCard)) {
                            qkjTqcourseDto.setIsBuy(1);
                        } else {
                            qkjTqcourseDto.setIsBuy(0);
                        }
                        Integer purchasedMembers = 0;
                        if (qkjTqcourseDto.getZq() == 2) {
                            List<QkjTqcourse> list1 = qkjTqcourseDao.findTqListForZq(qkjTqcourseDto.getId().intValue());
                            if (list1 != null && !list1.isEmpty()) {
                                for (QkjTqcourse q : list1) {
                                    if (q.getPurchasedMembers() != null) {
                                        purchasedMembers = purchasedMembers + q.getPurchasedMembers();
                                    }

                                }
                                qkjTqcourseDto.setPurchasedMembers(purchasedMembers);
                            }
                        }
                        return qkjTqcourseDto;
                    }).collect(Collectors.toList());
                    if (start == 1) {
                        QkjTqcourseDto qkjTqcourseDto = CopyUtil.copy(qkjTqcourse, QkjTqcourseDto.class);

                        List<SalesOrdersMain> tqcourseOrderList = orderDao.findTqcourseOrderList(memCard, 1, qkjTqcourse.getId().intValue());
                        if (tqcourseOrderList != null && !tqcourseOrderList.isEmpty()) {
                            if (StringUtils.isNotBlank(memCard) && judgeCoursePurchased(qkjTqcourse, memCard)) {
                                qkjTqcourseDto.setIsBuy(1);
                            } else {
                                qkjTqcourseDto.setIsBuy(0);
                            }
                        }

                        Integer purchasedMembers = 0;
                        Integer purchasedMembersTOW = 0;
                        if (qkjTqcourseDto.getZq() == 2) {
                            List<QkjTqcourse> list1 = qkjTqcourseDao.findTqListForZq(qkjTqcourseDto.getId().intValue());
                            if (list1 != null && !list1.isEmpty()) {
                                for (QkjTqcourse q : list1) {
                                    if (q.getPurchasedMembers() != null) {
                                        purchasedMembers = purchasedMembers + q.getPurchasedMembers();
                                        purchasedMembersTOW = purchasedMembersTOW + q.getPurchasedMembers()+q.getStudyNum();
                                    }
                                }
                                qkjTqcourseDto.setTotalClassHours(list1.size());
                                qkjTqcourseDto.setPurchasedMembers(purchasedMembers);
                                qkjTqcourseDto.setStudyNumTOW(purchasedMembersTOW);
                            }
                        }
                        qkjTqcourseDto.setIsController(1);
                        List<SalesCollectionMain> salesCollectionMainList = collectionDao.getCollectionInfo(memCard, qkjTqcourseDto.getId() + "", 1);
                        if (salesCollectionMainList != null & salesCollectionMainList.size() > 0) {
                            qkjTqcourseDto.setIsController(0);
                        }
                        data.put("info", qkjTqcourseDto);
                    }
                    if (coll != null && !coll.isEmpty()) {
                        data.put("list", coll);
                        if ("web".equals(from)) {
                            Map<String, Object> results = new HashMap<>();
                            results.put("results", data);
                            results.put("total", total);
                            return Result.success(results);
                        }
                    }
                    return Result.success(data);
                }
            }
        } else {
            //查询首页分类下数据列表
            List<Long> list = new ArrayList<>();
            if (cataId != null) {
                List<QkjCatalogs> byFuId = qkjCatalogsDao.findByFuId(cataId);
                if (byFuId != null && !byFuId.isEmpty()) {
                    for (QkjCatalogs qkjCatalogs : byFuId) {
                        List<QkjCatalogs> logs = qkjCatalogsDao.findByFuId(qkjCatalogs.getId().intValue());
                        if (logs != null && !logs.isEmpty()) {
                            for (QkjCatalogs q : logs) {
                                list.add(q.getId());
                            }
                        } else {
                            list.add(qkjCatalogs.getId());
                        }

                    }
                }
            }
            List<QkjTqcourse> data = null;
            if (list != null && !list.isEmpty()) {
                String join = StringUtils.join(list, ",");
                log.info("join======" + join);
                total = qkjTqcourseDao.getIndexDataCounts(list);
                data = qkjTqcourseDao.getIndexData(list, (start - 1) * size, size);
            } else {
                list.add(cataId.longValue());
                log.info("cataId======" + cataId);
                total = qkjTqcourseDao.getIndexDataCounts(list);
                data = qkjTqcourseDao.getIndexData(list, (start - 1) * size, size);
            }

            List<QkjTqcourseDto> coll = data.stream().map(item -> {
                QkjTqcourseDto qkjTqcourseDto = CopyUtil.copy(item, QkjTqcourseDto.class);
                qkjTqcourseDto.setStudyNumTOW(item.getPurchasedMembers()+item.getStudyNum());
                List<SalesOrdersMain> tqcourseOrderList = orderDao.findTqcourseOrderList(memCard, 1, item.getId().intValue());
                if (tqcourseOrderList != null && !tqcourseOrderList.isEmpty()) {
                    qkjTqcourseDto.setIsBuy(1);
                } else {
                    qkjTqcourseDto.setIsBuy(0);
                }
                Integer IsBuy = judgeIsBuy(memCard, item.getId());
                if(IsBuy == 1){
                    qkjTqcourseDto.setIsBuy(IsBuy);
                }
                Integer purchasedMembers = 0;
                Integer purchasedMembersTOW = 0;
                if (qkjTqcourseDto.getZq() == 2) {
                    List<QkjTqcourse> list1 = qkjTqcourseDao.findTqListForZq(qkjTqcourseDto.getId().intValue());
                    if (list1 != null && !list1.isEmpty()) {
                        for (QkjTqcourse q : list1) {
                            if (q.getPurchasedMembers() != null) {
                                purchasedMembers = purchasedMembers + q.getPurchasedMembers();
                                purchasedMembersTOW = purchasedMembersTOW + q.getPurchasedMembers()+q.getStudyNum();
                            }
                        }
                        qkjTqcourseDto.setPurchasedMembers(purchasedMembers);
                        qkjTqcourseDto.setStudyNumTOW(purchasedMembersTOW);
                    }
                }
                return qkjTqcourseDto;
            }).collect(Collectors.toList());
            if (coll != null && !coll.isEmpty()) {
                if ("web".equals(from)) {
                    Map<String, Object> results = new HashMap<>();
                    results.put("results", coll);
                    results.put("total", total);
                    return Result.success(results);
                }
                return Result.success(coll);
            }
        }
        return Result.failed(BizCodeEnum.DATA_EMPTY);
    }

    /**
     * 判断当前课程是否是专区已购买的
     * @param memCard 用户唯一标识
     * @param tqcourseId 课程id
     * @return 1: 购买  0: 未购买
     */
    public Integer judgeIsBuy(String memCard , Long tqcourseId){
        Integer isBuy = 0;
        List<Integer> tqcoursezqId = qkjTqcourseDao.getTqcoursezqIdByTqcourseId(tqcourseId);
        for (int i = 0; i < tqcoursezqId.size(); i++) {
            List<SalesOrdersMain> tqcourseOrderList1 = orderDao.findTqcourseOrderList(memCard, 1, tqcoursezqId.get(i));
            if (tqcourseOrderList1 != null && !tqcourseOrderList1.isEmpty()) {
                isBuy = 1;
            }
        }
        return isBuy;
    }

    @Override
    public Result<QkjTqcourseCourseDto> findTqCourseCourseInfo(Long id) {
        Optional<QkjTqcourseCourse> byId = qkjTqcourseCourseDao.findById(id);
        if (byId != null && byId.isPresent()) {
            QkjTqcourseCourse qkjTqcourseCourse = byId.get();
            QkjTqcourseCourseDto copy = CopyUtil.copy(qkjTqcourseCourse, QkjTqcourseCourseDto.class);
            return Result.success(copy);
        }
        return Result.failed(BizCodeEnum.DATA_EMPTY);
    }

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
    public Object addVideoPlayRecorde(String memCard, int objType, int objId, int playTime, int totalLearnTime, String ip) {
        if(StringUtils.isBlank(memCard)){
            log.info("addVideoPlayRecorde memCard is null memCard:{} objType:{} objId:{} ", memCard, objType, objId);
            return Result.success(false);
        }
        QkjVedioPlayRecord record = qkjVedioPlayRecordDao.findByMemCardAndObjTypeAndObjId(memCard, objType, objId);
        int isOver = 0;
        int endtime = playTime;
        Integer pobjId = null;
        if (objType == 1) {
            QkjTqcourseCourse course = qkjTqcourseCourseDao.findById((long) objId).get();
            if (course == null) {
                playTime = 0;
            } else {
                pobjId = course.getTqcourseId().intValue();
                Integer vedioLength = course.getVodLength() * 1000;
                if (vedioLength - playTime <= 20000) {
//                    playTime = 0;
                    endtime = vedioLength;
                    isOver = 1;
                }
            }
        }

        int lookUp = 2;//是否在线观看：针对直播：1在线2回看
        if(Objects.equals(playTime,-1)){
            lookUp = 1;
        }
        boolean isEnd = false;

        if(objType == 2){
            QkjLive qkjLive = qkjLiveDao.findById((long) objId).orElse(null);
            if(Objects.nonNull(qkjLive) && Objects.equals(qkjLive.getLiveStatus(), 2)){
                isEnd = true;
            }
            try {
                if (qkjLive == null) {
                    playTime = 0;
                } else {
                    if (qkjLive.getVodLength() == null) {
                        return Result.failed("请设置数据库中直播的总时长字段");
                    }
                    if(playTime == -1){
                        endtime = qkjLive.getVodLength() * 1000;
                        playTime = qkjLive.getVodLength() * 1000;
                    }
                    Integer vedioLength = qkjLive.getVodLength() * 1000;
                    if (vedioLength - playTime <= 20000 ) {
//                          playTime = 0;
                        endtime = vedioLength;
                        isOver = 1;
                    }
                }

            } catch (Exception e) {
                log.error("e:{}",e);
            }
        }

        if (record == null) {
            record = new QkjVedioPlayRecord();
            record.setMemCard(memCard);
            record.setPobjId(pobjId);
            record.setObjId(objId);
            record.setObjType(objType);
            record.setPlayTime(playTime);
            record.setOprTime(Calendar.getInstance());
            record.setStudyPercent(Double.valueOf(isOver));
            if (!isEnd) {
                qkjVedioPlayRecordDao.save(record);
                if(objType != 2){
                    //统计课程学习人数
                    updateStudyNum(objType, objId);
                }
            }

        } else {
            record.setPlayTime(playTime);
            record.setPobjId(pobjId);
            record.setOprTime(Calendar.getInstance());
            if (!isEnd) {
                qkjVedioPlayRecordDao.save(record);
            }
        }

        if (totalLearnTime != 0) {
            QkjVedioPlayRecordLog records = new QkjVedioPlayRecordLog();
            records.setMemCard(memCard);
            records.setObjId(objId);
            records.setObjType(objType);
            records.setEndPlayTime(endtime);
            if(Objects.equals(objType,2)){//直播的话直接给固定1分钟
                //如果是刚进来就出去，使用传进来的时间
                if(totalLearnTime >= PlayRecordLogConstants.TIME_GAP){
                    totalLearnTime = PlayRecordLogConstants.TIME_GAP;
                }
            }
            records.setLearnTime(totalLearnTime);
            records.setOprTime(Calendar.getInstance());
            records.setIsOver(isOver);
            records.setIp(ip);


            records.setLookUp(lookUp);
            if (!isEnd) {
                qkjVedioPlayRecordLogDao.save(records);
            }

            if (totalLearnTime >= 600000 && objType != 2) {
                QkjMemberTask task = taskService.judeFinishTask(memCard, 19);
                if (task != null) {
                    taskService.dailyCheckIn(memCard, 19, 0);
                }
            }
        }
        updateStudyPercent(memCard, objType, objId);
        return Result.success(true);
    }


    public Object saveplaylog(String memCard, int liveId, int learnTime){
        QkjVideoPlayLog playlog = new QkjVideoPlayLog();
        playlog.setMemCard(memCard);
        playlog.setLiveid(liveId);
        playlog.setLearntime(learnTime);
        playlog.setLogtime(Calendar.getInstance());
        qkjVideoPlayLogDao.save(playlog);
        return Result.success(true);
    }


    //统计课程学习人数
    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
    @Async
    public void updateStudyNum(Integer objType, Integer objId) {
        try {
            if (objType == 1) {
                QkjTqcourseCourse course = qkjTqcourseCourseDao.findById(objId.longValue()).get();
                if (course != null) {

                    QkjTqcourse tqcourse = qkjTqcourseDao.findById(course.getTqcourseId().longValue()).get();
                    if (tqcourse != null) {
                        tqcourse.setStudyNum(qkjVedioPlayRecordDao.findMemberCountByPobjId(1, course.getTqcourseId().intValue()).intValue());
                        qkjTqcourseDao.save(tqcourse);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    //统计课程学习进度
    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
    @Async
    public void updateStudyPercent(String memCard, Integer objType, Integer objId) {
        try {
            QkjVedioPlayRecord record = qkjVedioPlayRecordDao.findByMemCardAndObjTypeAndObjId(memCard, objType, objId);
            if (record != null && objType == 1 && record.getStudyPercent() < 1.1) {
                QkjTqcourseCourse course = qkjTqcourseCourseDao.findById(objId.longValue()).get();
                if (course != null) {
                    //更新子课时学习进度
                    Integer vedioLength = course.getVodLength() * 1000;
                    QkjVedioPlayRecordLog recordLog = qkjVedioPlayRecordLogDao.findMaxEndPlayTime(memCard, objType, objId);
                    DecimalFormat df = new DecimalFormat("0.00");
                    if (recordLog != null && recordLog.getEndPlayTime() != null) {
                        Double result = Double.valueOf(df.format((float) recordLog.getEndPlayTime() / vedioLength));
                        if (result == 0) {
                            result = 0.01;
                        }
                        record.setStudyPercent(result);
                        qkjVedioPlayRecordDao.save(record);
                    }

                    //更新主课学习进度
                    QkjTqcourse tqcourse = qkjTqcourseDao.findById(course.getTqcourseId().longValue()).get();
                    if (tqcourse != null) {
                        BigDecimal totalPercentRst = qkjVedioPlayRecordDao.findTotalPercentByPobjId(memCard, objType, course.getTqcourseId().intValue());
                        Double tqPercent = 0d;
                        if (totalPercentRst != null) {
                            Double coursesTotalPercent = totalPercentRst == null ? 0 : totalPercentRst.doubleValue();
                            tqPercent = Double.valueOf(df.format(coursesTotalPercent / tqcourse.getTotalClassHours()));
                            if (coursesTotalPercent > 0 && tqPercent == 0) {
                                tqPercent = 0.01;
                            }
                        }

                        QkjVedioPlayRecord tqRecord = qkjVedioPlayRecordDao.findByMemCardAndObjTypeAndObjId(memCard, 7, course.getTqcourseId().intValue());
                        if (tqRecord != null) {
                            tqRecord.setOprTime(Calendar.getInstance());
                            tqRecord.setStudyPercent(tqPercent);
                            qkjVedioPlayRecordDao.save(tqRecord);
                        } else {
                            tqRecord = new QkjVedioPlayRecord();
                            tqRecord.setMemCard(memCard);
                            tqRecord.setObjType(7);
                            tqRecord.setObjId(course.getTqcourseId().intValue());
                            tqRecord.setStudyPercent(tqPercent);
                            tqRecord.setOprTime(Calendar.getInstance());
                            qkjVedioPlayRecordDao.save(tqRecord);
                        }
                    }

                }
            }else if(record != null && objType == 2 && record.getStudyPercent() < 1.1){
                QkjLive qkjLive = qkjLiveDao.findById(objId.longValue()).get();
                if (qkjLive != null) {
                    //更新子课时学习进度
                    Integer vedioLength = qkjLive.getVodLength() * 1000;
                    //获取到所有回看时间的总和
                    List<Integer> PlayTime = qkjVedioPlayRecordLogDao.findCountPlayTime(memCard, objType, objId, 2);
                    Integer countPlayTime = PlayTime.stream().mapToInt(Integer::intValue).sum();
                    DecimalFormat df = new DecimalFormat("0.00");
                    if (countPlayTime!=null && countPlayTime!=0) {
                        Double result = Double.valueOf(df.format((float) countPlayTime / vedioLength));
                        if (result == 0) {
                            result = 0.01;
                        }
                        if(result >1){
                            result = 1D;
                        }
                        record.setStudyPercent(result);
                        qkjVedioPlayRecordDao.save(record);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public Result saveCommon(Long id, String memCard, String content) {
        QkjMember byMemCard = memberDao.findByMemCard(memCard);
        QkjTqcourseComments qkjTqcourseComments = new QkjTqcourseComments();
        qkjTqcourseComments.setContent(content);
        qkjTqcourseComments.setTqcourseId(id.intValue());
        qkjTqcourseComments.setOprTime(new Date());
        if (byMemCard != null) {
            qkjTqcourseComments.setCommentMemHear(byMemCard.getMemHeadimg());
            qkjTqcourseComments.setCommentMemName(byMemCard.getMemNickname());
        }
        qkjTqcourseCommentsDao.save(qkjTqcourseComments);
        return Result.success(BizCodeEnum.SUCCESS);
    }

    /**
     * 校验提取码
     *
     * @param memCard
     * @param code
     * @param id
     * @return
     */
    @Override
    public Result checkCode(String ip, String memCard, String code, Long id) {

        String count = (String) stringRedisTemplate.opsForValue().get("extracted_code" + memCard + id);
        if (!StringUtils.isEmpty(count)) {
            if (Integer.parseInt(count) > 6) {
                return Result.failed("您今日免费次数已用完，请明日再来！");
            }
        } else {
            count = "0";
        }
        QkjTqcourseCourse qkjTqcourseCourse = qkjTqcourseCourseDao.findById(id).get();
        QkjTqcourse qkjTqcourse = qkjTqcourseDao.findById(qkjTqcourseCourse.getTqcourseId().longValue()).get();
        if (code.equals(qkjTqcourse.getExtractedCode())) {
            stringRedisTemplate.opsForValue().set("extracted_code" + memCard + id, String.valueOf(Integer.parseInt(count) + 1), 1, TimeUnit.DAYS);
            orderService.addFreeBuyApi(memCard, 1, Integer.parseInt(qkjTqcourse.getId().toString()), 1, "", ip, 1, null);
            return Result.success("校验通过");
        } else {
            List<QkjTqcourse> tqListForZqs = qkjTqcourseDao.findTqListFortqId(qkjTqcourse.getId().intValue());
            if (!ListUtils.isEmpty(tqListForZqs)) {
                for (QkjTqcourse zq : tqListForZqs) {
                    if (Integer.valueOf(1).equals(zq.getIsSpecialCourse())) {
                        if (code.equals(zq.getExtractedCode())) {
                            stringRedisTemplate.opsForValue().set("extracted_code" + memCard + id, String.valueOf(Integer.parseInt(count) + 1), 1, TimeUnit.DAYS);
                            orderService.addFreeBuyApi(memCard, 1, Integer.parseInt(qkjTqcourse.getId().toString()), 1, "", ip, 1, null);
                            return Result.success("校验通过");
                        }
                    }
                }
            }
        }


        return Result.failed("校验失败");
    }

    @Override
    public QkjTqcourse findById(Integer id) {
        Optional<QkjTqcourse> byId = qkjTqcourseDao.findById(id.longValue());
        if (byId != null && byId.isPresent()) {
            return byId.get();
        }
        return null;
    }


    //判断课程是否过期
    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
    protected boolean judgeCoursePurchased(QkjTqcourse tqcourse, String memCard) {
        log.info("tqId======" + tqcourse.getId());
        QkjPurchasedRecords records = orderService.findPurchasedRecords(memCard, 1, tqcourse.getId().intValue(), 1);
        Boolean isPurchased = false;
        if (records != null) {
            isPurchased = true;
        } else if (tqcourse.getZq() == 2) {
            List<QkjTqcourse> liveSeries = qkjTqcourseDao.findTqListForZq(tqcourse.getId().intValue(), 0, 1000);
            for (QkjTqcourse series : liveSeries) {
                records = orderService.findPurchasedRecords(memCard, 1, series.getId().intValue(), 1);
                if (records != null) {
                    isPurchased = true;
                    break;
                }
            }
        }
        return isPurchased;
    }

    /**
     * 课程学习人数加一
     *
     * @param course 课程实体对象
     */
    private void studyCountPlus1(QkjTqcourse course) {
        Integer studyCount = course.getStudyNum();
        // 对于int的包装类，该值有可能为null
        if (studyCount == null) studyCount = 0;
        // JPA框架可直接操作实体的状态，无需手动更新到数据库
        course.setStudyNum(++studyCount);
    }

}
