package com.sqx.modules.course.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sqx.common.exception.SqxException;
import com.sqx.common.utils.ApiAccessLimitUtil;
import com.sqx.common.utils.DateUtils;
import com.sqx.common.utils.PageUtils;
import com.sqx.common.utils.Result;
import com.sqx.modules.app.entity.UserEntity;
import com.sqx.modules.app.service.UserService;
import com.sqx.modules.app.utils.JwtUtils;
import com.sqx.modules.common.dao.CommonInfoDao;
import com.sqx.modules.common.entity.CommonInfo;
import com.sqx.modules.course.dao.CourseCollectDao;
import com.sqx.modules.course.dao.CourseDao;
import com.sqx.modules.course.dao.CourseDetailsDao;
import com.sqx.modules.course.dao.CourseUserDao;
import com.sqx.modules.course.entity.Course;
import com.sqx.modules.course.entity.CourseCollect;
import com.sqx.modules.course.entity.CourseDetails;
import com.sqx.modules.course.entity.CourseUser;
import com.sqx.modules.course.service.CourseDetailsService;
import com.sqx.modules.course.vo.CourseDetailsIn;
import com.sqx.modules.course.vo.CourseDetailsSetVo;
import com.sqx.modules.orders.dao.OrdersDao;
import com.sqx.modules.orders.service.OrdersService;
import com.sqx.modules.redisService.impl.RedisServiceImpl;
import com.sqx.modules.utils.EasyPoi.ExcelUtils;
import com.sqx.modules.utils.HttpClientUtil;
import com.sqx.modules.utils.SenInfoCheckUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;

@Service
@Slf4j
public class CourseDetailsServiceImpl extends ServiceImpl<CourseDetailsDao, CourseDetails> implements CourseDetailsService {

    @Autowired
    private CourseDao courseDao;
    @Autowired
    private CourseCollectDao courseCollectDao;
    @Autowired
    private JwtUtils jwtUtils;
    @Autowired
    private CourseUserDao courseUserDao;
    @Autowired
    private OrdersService ordersService;
    @Autowired
    private UserService userService;
    @Autowired
    private OrdersDao ordersDao;
    @Autowired
    private CommonInfoDao commonInfoDao;
    @Autowired
    private RedisServiceImpl redisServiceImpl;
    @Autowired
    private CourseDetailsDao courseDetailsDao;


    @Override
    @CacheEvict(cacheNames = {"courseSets", "courseCount"}, key = "#courseDetails.courseId")
    public Result insert(CourseDetails courseDetails) {
        if (courseDetails.getGoodNum() == null) {
            courseDetails.setGoodNum(0);
        }
        baseMapper.insert(courseDetails);
        return Result.success();
    }

    @Override
    @CacheEvict(cacheNames = {"courseSets", "courseCount"}, key = "#courseDetails.courseId")
    public Result updateCourseDetails(CourseDetails courseDetails) {
        baseMapper.updateById(courseDetails);
        return Result.success();
    }

    @Override
    public Result deleteCourseDetails(String ids) {
        String[] split = ids.split(",");
        baseMapper.deleteCourseDetails(split);
        return Result.success();
    }

    /**
     * 校验用户是否达到免费播放购买次数
     *
     * @param userId 用户id
     * @return true 可观看
     */
    private boolean checkFreeWatchPayCount(Long userId) {
        Boolean isExpire = redisServiceImpl.getFreeWatchTimeIsExpire(userId);
        if (isExpire == null) {
            Integer count = ordersDao.countPayOrderByDay(userId);
            CommonInfo needCountCommonInfo = commonInfoDao.selectOne(new LambdaQueryWrapper<CommonInfo>()
                    .eq(CommonInfo::getType, 916));
            CommonInfo freeTimeCommonInfo = commonInfoDao.selectOne(new LambdaQueryWrapper<CommonInfo>()
                    .eq(CommonInfo::getType, 917));
            if (needCountCommonInfo == null || freeTimeCommonInfo == null
                    || StrUtil.isBlank(needCountCommonInfo.getValue()) || StrUtil.isBlank(freeTimeCommonInfo.getValue())) {
                log.warn("系统未配置全免次数或时间");
                return false;
            }

            // 购买次数超过，设置redis标识
            if (count >= Integer.parseInt(needCountCommonInfo.getValue())) {
                redisServiceImpl.setFreeWatchTime(userId, Integer.parseInt(freeTimeCommonInfo.getValue()) * 60, false);
                // 触发计时
                redisServiceImpl.getFreeWatchTimeIsExpire(userId);
                isExpire = false;
            } else {
                isExpire = true;
            }
        }
        return !isExpire;

    }

    //更新 播放量 周播放量
    private void setCourseView(Course course) {
        if (course.getViewCounts() == null) {
            course.setViewCounts(1);
        } else {
            course.setViewCounts(course.getViewCounts() + 1);
        }
        if (ApiAccessLimitUtil.isAccessAllowed(course.getCourseId().toString(), "updateWeekCourseView", 1, 600)) {
            int courseViewCount = redisServiceImpl.getCourseWeekViewCount(course.getCourseId());
            course.setWeekView(courseViewCount);
        }
        courseDao.update(null, new LambdaUpdateWrapper<Course>()
                .eq(Course::getCourseId, course.getCourseId())
                .set(Course::getViewCounts, course.getViewCounts())
                .set(Course::getWeekView, course.getWeekView()));
    }

    @Override
    public Result courseSets(Long userId, Long courseId, Integer sort) {
        try {
            //观看记录
            CourseCollect courseCollect = courseCollectDao.selectOne(new QueryWrapper<CourseCollect>()
                    .select("course_id", "course_details_id")
                    .eq("course_id", courseId).eq("user_id", userId)
                    .eq("classify", 3).last("limit 1"));
            //是否追剧
            Integer collect = courseCollectDao.selectCount(new QueryWrapper<CourseCollect>()
                    .eq("user_id", userId).eq("course_id", courseId)
                    .eq("classify", 1).last("limit 1"));
            Course bean = courseDao.selectById(courseId);
            if (bean == null) {
                log.error("未找到该剧集 用户id:{} 剧集:{}", userId, courseId);
                return Result.error("未找到该剧集");
            }
            //查询用户是否购买了整集
            CourseUser courseUser = courseUserDao.selectCourseUser(courseId, userId);
            // 每天购买超过上限，获得免费时间段资格
            boolean freeWatch = checkFreeWatchPayCount(userId);
            int startSort = 0;
            int endSort = 5;
            if (sort == null) {
                if (courseCollect != null) {
                    CourseDetails courseDetails = baseMapper.selectOne(new QueryWrapper<CourseDetails>()
                            .select("sort")
                            .eq("course_details_id", courseCollect.getCourseDetailsId()).eq("course_id", courseCollect.getCourseId()).last("limit 1"));
                    sort = courseDetails.getSort();
                }
            }
            List<CourseDetailsSetVo> courseDetailsSetVos;
            if (freeWatch || courseUser != null) {
                courseDetailsSetVos = baseMapper.courseSets(courseId, 2, null);
            } else {
                courseDetailsSetVos = baseMapper.courseSets(courseId, 1, bean.getWholesalePrice());
            }
            if (sort != null && sort > 2) {
                startSort = sort - 3;
                endSort = sort + 3;
                if (courseDetailsSetVos.size() < endSort) {
                    startSort = courseDetailsSetVos.size() - 5;
                    endSort = courseDetailsSetVos.size() + 1;
                }
            }
            //已购买剧集
            Set<Long> detailsId = new HashSet<>();
            if ((!freeWatch)) {
                detailsId = courseUserDao.selectUserCourseDetailsId(courseId, userId);
            }
            AtomicReference<CourseDetailsSetVo> current = new AtomicReference<>(new CourseDetailsSetVo());
            Set<Long> finalDetailsId = detailsId;
            int finalStartSort = startSort;
            int finalEndSort = endSort;
            courseDetailsSetVos.parallelStream().forEach(s -> {
                //当前
                if (courseCollect != null && s.getCourseDetailsId().equals(courseCollect.getCourseDetailsId())) {
                    s.setCurrent(1);
                    current.set(s);
                }
                // 不免费  3集以后    (已买的不为空  并不在已买的包含)
                if (!freeWatch && s.getSort() > 3 && (CollectionUtil.isEmpty(finalDetailsId) || !finalDetailsId.contains(s.getCourseDetailsId()))) {
                    s.setVideoUrl(null);
                }
                if (s.getSort() > finalStartSort && s.getSort() < finalEndSort) {
                    Integer isGood = courseCollectDao.selectCount(new QueryWrapper<CourseCollect>()
                            .eq("user_id", userId).eq("course_details_id", s.getCourseDetailsId()).eq("classify", 2).last("limit 1"));
                    s.setIsGood(isGood == null || isGood == 0 ? 0 : 1);
                }
            });
            if (courseCollect == null) {
                courseDetailsSetVos.get(0).setCurrent(1);
                current.set(courseDetailsSetVos.get(0));
            }
            ThreadUtil.execAsync(() -> {
                setCourseView(bean);
            });
            Map<String, Object> map = new HashMap<>();
            map.put("current", current.get());
            map.put("price", freeWatch ? 0 : bean.getPrice());
            map.put("title", bean.getTitle());
            map.put("collect", collect == null || collect.equals(0) ? 0L : 1L);
            map.put("list", courseDetailsSetVos);
            return new Result().put("data", map);
        } catch (Exception e) {
            log.error("请求剧集异常打印:",e);
            return Result.error("请求剧集失败");
        }
    }

    @Override
    public Result selectCourseDetailsById(Long id, String token, String courseDetailsId) {
        Course bean = courseDao.selectById(id);
//        if (bean.getViewCounts() == null) {
//            bean.setViewCounts(1);
//        } else {
//            bean.setViewCounts(bean.getViewCounts() + 1);
//        }
//        courseDao.updateById(bean);

        setCourseView(bean);

        Long userId = null;
        if (StringUtils.isNotEmpty(token)) {
            Claims claims = jwtUtils.getClaimByToken(token);
            if (claims != null && !jwtUtils.isTokenExpired(claims.getExpiration())) {
                userId = Long.parseLong(claims.getSubject());
            }
        }
        bean.setIsCollect(0);
        if (userId != null) {
            bean.setIsCollect(courseCollectDao.selectCount(new QueryWrapper<CourseCollect>().eq("user_id", userId).eq("classify", 1).eq("course_id", bean.getCourseId())));
            UserEntity userEntity = userService.selectUserById(userId);
            //查询用户是否购买了整集
            CourseUser courseUser = courseUserDao.selectCourseUser(id, userId);
            // 每天购买超过上限，获得免费时间段资格
            boolean freeWatch = checkFreeWatchPayCount(userId);
            if (freeWatch || courseUser != null || (userEntity != null && userEntity.getMember() != null && userEntity.getMember() == 2)) {
                bean.setListsDetail(baseMapper.findByCourseId(id, userId));
            } else {
                List<CourseDetails> list = baseMapper.findByCourseIdNotUrl(id, userId);
                bean.setListsDetail(list);
                //查询用户是否单独购买了集
                List<CourseUser> courseUsers = courseUserDao.selectCourseUserList(id, userId);
                if (courseUsers.size() > 0) {
                    for (CourseUser courseUser1 : courseUsers) {
                        for (CourseDetails courseDetails : bean.getListsDetail()) {
                            if (courseUser1.getCourseDetailsId().equals(courseDetails.getCourseDetailsId())) {
                                CourseDetails courseDetails1 = baseMapper.selectById(courseDetails.getCourseDetailsId());
                                courseDetails.setVideoUrl(courseDetails1.getVideoUrl());
                            }
                        }
                    }
                }
            }
            /*for (CourseDetails courseDetails:bean.getListsDetail()){
                courseDetails.setIsCollect(courseCollectDao.selectCount(new QueryWrapper<CourseCollect>()
                        .eq("user_id", userId).eq("course_details_id", courseDetails.getCourseDetailsId()).eq("classify",1)));
                courseDetails.setIsGood(courseCollectDao.selectCount(new QueryWrapper<CourseCollect>()
                        .eq("user_id", userId).eq("course_details_id", courseDetails.getCourseDetailsId()).eq("classify",2)));
            }*/

        } else {
            bean.setListsDetail(baseMapper.findByCourseIdNotUrl(id, null));
        }
        if (courseDetailsId != null) {
            if (bean.getListsDetail().size() > 0) {
                for (CourseDetails courseDetails : bean.getListsDetail()) {
                    if (courseDetails.getCourseDetailsId().equals(Long.parseLong(courseDetailsId))) {
                        //微信内
                        String url = "https://api.weixin.qq.com/wxa/sec/vod/getmedialink?access_token=" + SenInfoCheckUtil.getMpToken();
                        JSONObject jsonObject = new JSONObject();
//                        jsonObject.put("media_id", courseDetails.getWxCourseDetailsId());
                        jsonObject.put("t", (new Date().getTime() / 1000) + 7200);
                        String s = HttpClientUtil.doPostJson(url, jsonObject.toJSONString());
                        JSONObject jsonObject1 = JSONObject.parseObject(s);
                        String errcode = jsonObject1.getString("errcode");
                        if (!"0".equals(errcode)) {
                            return Result.error("获取微信播放链接失败：" + jsonObject1.getString("errmsg"));
                        }
                        JSONObject media_info = jsonObject1.getJSONObject("media_info");
                        String mp4_url = media_info.getString("mp4_url");
//                        courseDetails.setWxUrl(mp4_url);
                        break;
                    }
                }
            }
        }
        CourseCollect courseCollect = courseCollectDao.selectOne(Wrappers.<CourseCollect>lambdaQuery()
                .select(CourseCollect::getCourseDetailsId)
                .eq(CourseCollect::getCourseId, id)
                .eq(CourseCollect::getClassify, 3)
                .eq(CourseCollect::getUserId, userId)
                .orderByDesc(CourseCollect::getUpdateTime).last("limit 1")
        );
        if (courseCollect != null && courseCollect.getCourseDetailsId() != null) {
            CourseDetails courseDetails = courseDetailsDao.selectOne(new LambdaQueryWrapper<CourseDetails>().eq(CourseDetails::getCourseId, id)
                    .eq(CourseDetails::getCourseDetailsId, courseCollect.getCourseDetailsId()));
            if (courseDetails != null) {
                bean.setCourseDetailsId(courseDetails.getCourseDetailsId());
                bean.setCourseDetailsName(courseDetails.getCourseDetailsName());
                bean.setCourseDetailsCount(courseDetails.getCourseDetailsCount());
            }
        } else {
            //默认取第一集
            CourseDetails courseDetails = courseDetailsDao.selectOne(Wrappers.<CourseDetails>lambdaQuery().eq(CourseDetails::getCourseId, id)
                    .orderByAsc(CourseDetails::getSort).last(" limit 1"));
            if (courseDetails != null) {
                bean.setCourseDetailsId(courseDetails.getCourseDetailsId());
                bean.setCourseDetailsName(courseDetails.getCourseDetailsName());
                bean.setCourseDetailsCount(courseDetails.getCourseDetailsCount());
            }
        }
        return Result.success().put("data", bean);
    }

    @Override
    public Result selectCourseDetailsList(String token) {
        Long userId = null;
        if (StringUtils.isNotEmpty(token)) {
            Claims claims = jwtUtils.getClaimByToken(token);
            if (claims != null && !jwtUtils.isTokenExpired(claims.getExpiration())) {
                userId = Long.parseLong(claims.getSubject());
            }
        }
        Integer detailCount = baseMapper.selectCount(new LambdaQueryWrapper<CourseDetails>()
                .eq(CourseDetails::getGood, 1)
                .eq(CourseDetails::getIsPrice, 2));
        if (detailCount == null) {
            return Result.error("暂无推荐视频。");
        }
        PageHelper.startPage(RandomUtil.randomInt(1, detailCount / 10), 5);
        List<CourseDetails> list = baseMapper.selectList(new LambdaQueryWrapper<CourseDetails>()
                .eq(CourseDetails::getGood, 1)
                .eq(CourseDetails::getIsPrice, 2));
        if (userId != null) {
            Long finalUserId = userId;
            list.stream().forEach(s -> {
                s.setIsCollect(courseCollectDao.selectCount(new LambdaQueryWrapper<CourseCollect>()
                        .eq(CourseCollect::getUserId, finalUserId).eq(CourseCollect::getCourseId, s.getCourseId())
                        .eq(CourseCollect::getClassify, 1).last("limit 1")));
                s.setIsGood(courseCollectDao.selectCount(new LambdaQueryWrapper<CourseCollect>()
                        .eq(CourseCollect::getUserId, finalUserId).eq(CourseCollect::getCourseId, s.getCourseId())
                        .eq(CourseCollect::getCourseDetailsId, s.getCourseDetailsId())
                        .eq(CourseCollect::getClassify, 2).last("limit 1")));
            });
        }
        PageInfo<CourseDetails> pageInfo = new PageInfo<>(list);
        return Result.success().put("data", PageUtils.page(pageInfo));
    }

    @Override
    public Result courseDetailsListExcelIn(MultipartFile file, Long courseId) throws IOException {
        Course course = courseDao.selectById(courseId);
        if (course == null) {
            return Result.error("所选剧不存在");
        }
        List<CourseDetailsIn> courseDetailsList = ExcelUtils.importExcel(file, 2, 1, CourseDetailsIn.class);
        if (CollectionUtils.isEmpty(courseDetailsList)) {
            return Result.error("Excel数据为空，excel转化失败！");
        }
        //当前行索引（Excel的数据从第几行开始,就填写几）
        int index = 4;
        //失败条数
        int repeat = 0;
        //成功条数
        int successIndex = 0;
        //空数据
        int emptyCount = 0;
        for (CourseDetailsIn courseDetailsIn : courseDetailsList) {
            if (courseDetailsIn.getCourseDetailsName() == null) {
                emptyCount++;
                continue;
            }
            if (courseDetailsIn.getIsPrice() != 2) {
                if (courseDetailsIn.getPrice() == null || courseDetailsIn.getPrice().compareTo(BigDecimal.ZERO) <= 0) {
                    return Result.error("第【" + index + "】行数据为收费,但并没有设置价格");
                }
            }
            index++;
            Integer count = baseMapper.selectCount(new QueryWrapper<CourseDetails>().eq("course_details_name", courseDetailsIn.getCourseDetailsName()).eq("course_id", courseId));
            if (count <= 0) {
                CourseDetails courseDetails = new CourseDetails();
                courseDetails.setCourseId(courseId);
                courseDetails.setCreateTime(DateUtils.format(new Date()));
                courseDetails.setViewCount(0L);
                courseDetails.setPlayCompleteCount(0L);
                BeanUtils.copyProperties(courseDetailsIn, courseDetails);
                int result = baseMapper.insert(courseDetails);
                if (result > 0) {
                    successIndex++;
                } else {
                    repeat++;
                }
            }

        }
        return Result.success("导入成功,共新增【" + successIndex + "】条,失败【" + (courseDetailsList.size() - successIndex - emptyCount) + "】条,其中过滤重复数据【" + repeat + "】条");
    }


}
