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

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
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.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sqx.common.utils.DateUtils;
import com.sqx.common.utils.PageUtils;
import com.sqx.common.utils.Result;
import com.sqx.modules.course.dao.CourseClassificationDao;
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.entity.Course;
import com.sqx.modules.course.entity.CourseCollect;
import com.sqx.modules.course.entity.CourseDetails;
import com.sqx.modules.course.service.CourseCollectService;
import com.sqx.modules.course.service.CourseDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Collectors;

@Service
public class CourseCollectServiceImpl extends ServiceImpl<CourseCollectDao, CourseCollect> implements CourseCollectService {

    private final CourseDao courseDao;
    @Autowired
    private CourseClassificationDao courseClassificationDao;
    @Autowired
    private CourseDetailsService courseDetailsService;

    private ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock(true);
    @Autowired
    private CourseDetailsDao courseDetailsDao;

    public CourseCollectServiceImpl(CourseDao courseDao) {
        this.courseDao = courseDao;
    }

    @Override
    @CacheEvict(value = "app:courseCollect", key = "#courseCollect.userId")
    public Result insertCourseCollect(CourseCollect courseCollect) {

//        reentrantReadWriteLock.writeLock().lock();
        try {
            if (courseCollect.getClassify() == 3) {
                if (courseCollect.getCourseId() == null || courseCollect.getCourseDetailsId() == null) {
                    return Result.success("操作失败！");
                }
                QueryWrapper<CourseCollect> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("user_id", courseCollect.getUserId())
                        .eq("classify", 3)
                        .eq("course_id", courseCollect.getCourseId());
                queryWrapper.orderByDesc("create_time").last("limit 1");
                CourseCollect collect = baseMapper.selectOne(queryWrapper);
                if (collect != null) {
                    baseMapper.update(null, new LambdaUpdateWrapper<CourseCollect>()
                            .eq(CourseCollect::getCourseCollectId, collect.getCourseCollectId())
                            .eq(CourseCollect::getUserId, collect.getUserId())
                            .set(CourseCollect::getUpdateTime, DateUtil.now())
                            .set(CourseCollect::getCourseDetailsId, courseCollect.getCourseDetailsId()));
                    return Result.success("操作成功！");
                }
                collect = new CourseCollect()
                        .setUserId(courseCollect.getUserId())
                        .setCourseId(courseCollect.getCourseId())
                        .setCourseDetailsId(courseCollect.getCourseDetailsId())
                        .setClassify(3)
                        .setCreateTime(DateUtils.format(new Date()))
                        .setUpdateTime(DateUtils.format(new Date()));
                baseMapper.insert(collect);
                return Result.success("操作成功！");
            }
            // 1收藏 2点赞
            CourseCollect courseCollect1 = selectCourseCollectUserIdAnd(courseCollect.getUserId(), courseCollect.getCourseId(),
                    courseCollect.getClassify(), courseCollect.getClassify() == 1 ? null : courseCollect.getCourseDetailsId());
            if (courseCollect.getType() == 1) {
                if (courseCollect1 == null) {
                    if (courseCollect.getClassify().equals(1)) {
                        courseCollect.setCourseDetailsId(null);
                    }
                    courseCollect.setCreateTime(DateUtil.now());
                    courseCollect.setUpdateTime(courseCollect.getCreateTime());
                    baseMapper.insert(courseCollect);
                }
            } else {
                if (courseCollect1 != null) {
                    LambdaQueryWrapper<CourseCollect> queryWrapper = new LambdaQueryWrapper<>();
                    queryWrapper.eq(CourseCollect::getCourseCollectId, courseCollect1.getCourseCollectId());
                    queryWrapper.eq(CourseCollect::getCourseId, courseCollect1.getCourseId());
                    baseMapper.delete(queryWrapper);
                }
            }
            if (!courseCollect.getClassify().equals(1)) {
                upGoodNum(courseCollect, courseCollect.getType());
            }
            return Result.success("操作成功！");
        } catch (Exception e) {
            e.printStackTrace();
            log.error("收藏短剧出错了！" + e.getMessage());
        }
//        finally {
//            reentrantReadWriteLock.writeLock().unlock();
//        }
        return Result.error("系统繁忙,请稍后再试！");
    }

    /**
     * 更新点赞数量
     *
     * @param collect courseId 和 courseDetailsId 必须有值
     * @param isGood  1为加一 其它为 减一
     */
    public void upGoodNum(CourseCollect collect, Integer isGood) {
        LambdaQueryWrapper<CourseDetails> queryWrapper = new LambdaQueryWrapper<CourseDetails>()
                .eq(CourseDetails::getCourseId, collect.getCourseId())
                .eq(CourseDetails::getCourseDetailsId, collect.getCourseDetailsId());
        CourseDetails courseDetails = courseDetailsService.getOne(queryWrapper);

        LambdaUpdateWrapper<CourseDetails> updateWrapper = new LambdaUpdateWrapper<CourseDetails>()
                .eq(CourseDetails::getCourseId, collect.getCourseId())
                .eq(CourseDetails::getCourseDetailsId, collect.getCourseDetailsId())
                .set(CourseDetails::getGoodNum, courseDetails.getGoodNum() == null ? 0 : courseDetails.getGoodNum() - (isGood.equals(1) ? 1 : -1));
        courseDetailsService.update(updateWrapper);
    }

    @Override
    @CachePut(value = "app:courseCollect", key = "#userId")
    public Result selectByUserId(Integer page, Integer limit, Long userId, Integer classify) {
        PageHelper.startPage(page, limit);
        List<Course> courses = new ArrayList<>();
        if (classify.equals(1)) {
            //收藏记录
            courses = baseMapper.selectClassify1In3(userId);
        }else if (classify.equals(2)){
            //点赞
            courses = baseMapper.selectClassify2(userId);
        } else {
            //观看历史
            courses = baseMapper.selectClassify3ByUserId(userId);
        }

        //剧id
        Set<Long> courseIdList = new HashSet<>();
        //详情id
        Set<Long> courseDetailIds = new HashSet<>();
        //剧集-观看记录时间
        Map<Long,String> upTime = new HashMap<>();
        courses.forEach(s -> {
            if (s == null) {
                return;
            }
            courseIdList.add(s.getCourseId());
            courseDetailIds.add(s.getCourseDetailsId());
            upTime.put(s.getCourseId(),s.getUpdateTime());
        });
        List<Course> courseList = courseIdList.isEmpty() ? new ArrayList<>() :
                courseDao.selectList(new LambdaQueryWrapper<Course>().in(Course::getCourseId, courseIdList));

        List<CourseDetails> courseDetails1 = courseIdList.isEmpty() ? new ArrayList<>() :
                courseDetailsService.list(new LambdaQueryWrapper<CourseDetails>().in(CourseDetails::getCourseDetailsId, courseDetailIds));
        Map<Long, CourseDetails> courseDetailsMap = courseDetails1.stream()
                .collect(Collectors.toMap(CourseDetails::getCourseId, item -> item, (key1, key2) -> key1));

        if (CollectionUtil.isNotEmpty(courseList)) {
            for (Course course : courseList) {
                CourseDetails courseDetails = courseDetailsMap.getOrDefault(course.getCourseId(), null);
                course.setCourseDetailsCount(courseDetailsDao.countCourseByCourseId(course.getCourseId()));
                if (courseDetails != null) {
                    course.setCourseDetailsName(courseDetails.getCourseDetailsName());
                    course.setCourseDetailsId(courseDetails.getCourseDetailsId());
                }
                if (upTime.containsKey(course.getCourseId())) {
                    course.setUpdateTime(upTime.get(course.getCourseId()));
                }
            }
            courseList.sort(Comparator.comparing(Course::getUpdateTime).reversed());
        }
        PageInfo<Course> pageInfo = new PageInfo<>(courseList);
        return Result.success().put("data", PageUtils.page(pageInfo, true));
    }

    @Override
    public Result collectVideoSummary(Long userId) {
        return Result.success().put("data", baseMapper.selectSummary(userId));
    }

    @Override
    public CourseCollect selectCourseCollectUserIdAnd(Long userId, Long courseId, Integer classify, Long courseDetailsId) {
        return baseMapper.selectOne(new QueryWrapper<CourseCollect>()
                .eq(courseDetailsId != null, "course_details_id", courseDetailsId)
                .eq("user_id", userId)
                .eq("classify", classify)
                .eq("course_id", courseId));
    }


}
