package com.fs.course.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.fs.ad.enums.AdUploadType;
import com.fs.ad.service.IAdHtmlClickLogService;
import com.fs.common.BeanCopyUtils;
import com.fs.common.core.domain.R;
import com.fs.common.core.domain.ResponseResult;
import com.fs.common.core.redis.RedisCache;
import com.fs.common.utils.DateUtils;
import com.fs.common.utils.StringUtils;
import com.fs.course.config.CourseConfig;
import com.fs.course.domain.*;
import com.fs.course.dto.CoursePackageDTO;
import com.fs.course.mapper.*;
import com.fs.course.param.*;
import com.fs.course.param.newfs.UserCourseVideoPageParam;
import com.fs.course.vo.FsUserCourseVideoListUVO;
import com.fs.course.vo.FsUserCourseVideoQVO;
import com.fs.course.vo.FsUserCourseVideoVO;
import com.fs.course.vo.newfs.FsUserCourseVideoDetailsVO;
import com.fs.course.vo.newfs.FsUserCourseVideoPageListVO;
import com.fs.course.vo.newfs.FsUserVideoListVO;
import com.fs.course.vo.newfs.FsUserVideoQuestionVO;
import com.fs.his.domain.FsUser;
import com.fs.his.domain.FsUserIntegralLogs;
import com.fs.his.mapper.FsUserIntegralLogsMapper;
import com.fs.his.mapper.FsUserMapper;
import com.fs.his.param.WxSendRedPacketParam;
import com.fs.his.service.IFsStorePaymentService;
import com.fs.his.service.IFsUserService;
import com.fs.qw.domain.QwExternalContact;
import com.fs.qw.domain.QwUser;
import com.fs.qw.mapper.QwExternalContactMapper;
import com.fs.qw.mapper.QwUserMapper;
import com.fs.qwApi.Result.QwAddContactWayResult;
import com.fs.qwApi.param.QwAddContactWayParam;
import com.fs.qwApi.service.QwApiService;
import com.fs.sop.mapper.QwSopLogsMapper;
import com.fs.sop.mapper.SopUserLogsInfoMapper;
import com.fs.system.service.ISysConfigService;
import com.github.binarywang.wxpay.bean.transfer.TransferBillsResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import com.fs.course.service.IFsUserCourseVideoService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 课堂视频Service业务层处理
 *
 * @author fs
 * @date 2024-05-17
 */
@Service
public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
{
    private static final Logger logger = LoggerFactory.getLogger(FsUserCourseVideoServiceImpl.class);
    @Autowired
    private FsUserCourseVideoMapper fsUserCourseVideoMapper;
    @Autowired
    private IFsUserService fsUserService;
    @Autowired
    private FsUserCourseStudyLogMapper courseStudyLogMapper;

    @Autowired
    private FsUserCourseOrderMapper fsUserCourseOrderMapper;

    @Autowired
    private FsCourseQuestionBankMapper courseQuestionBankMapper;
    @Autowired
    private FsCourseWatchLogMapper courseWatchLogMapper;

    @Autowired
    private QwExternalContactMapper qwExternalContactMapper;
    @Autowired
    private ISysConfigService configService;
    @Autowired
    private FsCourseSopLogsMapper courseSopLogsMapper;
    @Autowired
    private QwApiService qwApiService;
    @Autowired
    private IAdHtmlClickLogService adHtmlClickLogService;
    @Autowired
    private QwUserMapper qwUserMapper;
    @Autowired
    private FsUserCourseVideoRedPackageMapper fsUserCourseVideoRedPackageMapper;
    @Autowired
    private FsCourseTrafficLogMapper fsCourseTrafficLogMapper;
    @Autowired
    private FsUserIntegralLogsMapper fsUserIntegralLogsMapper;
    @Autowired
    private FsUserMapper fsUserMapper;
    @Autowired
    private IFsStorePaymentService paymentService;
    @Autowired
    private FsCourseRedPacketLogMapper redPacketLogMapper;
    @Autowired
    private FsCourseFinishTempMapper fsCourseFinishTempMapper;

    @Autowired
    private QwSopLogsMapper qwSopLogsMapper;
    @Autowired
    private FsCourseLinkMapper courseLinkMapper;
    @Autowired
    RedisCache redisCache;
    /**
     * 查询课堂视频
     *
     * @param videoId 课堂视频主键
     * @return 课堂视频
     */
    @Override
    public FsUserCourseVideo selectFsUserCourseVideoByVideoId(Long videoId)
    {
        return fsUserCourseVideoMapper.selectFsUserCourseVideoByVideoId(videoId);
    }

    @Override
    public FsUserCourseVideoQVO selectFsUserCourseVideoByVideoIdVO(Long videoId) {
        FsUserCourseVideoQVO fsUserCourseVideoQVO=new FsUserCourseVideoQVO();
        FsUserCourseVideo courseVideo = fsUserCourseVideoMapper.selectFsUserCourseVideoByVideoId(videoId);

        BeanCopyUtils.copy(courseVideo,fsUserCourseVideoQVO);

        if (StringUtils.isNotEmpty(courseVideo.getQuestionBankId())){
            List<FsCourseQuestionBank> fsCourseQuestionBanks = courseQuestionBankMapper.selectFsCourseQuestionBankByIdVO(courseVideo.getQuestionBankId().split(","));
            fsUserCourseVideoQVO.setQuestionBankList(fsCourseQuestionBanks);
        }
        return fsUserCourseVideoQVO;
    }

    /**
     * 查询课堂视频列表
     *
     * @param fsUserCourseVideo 课堂视频
     * @return 课堂视频
     */
    @Override
    public List<FsUserCourseVideo> selectFsUserCourseVideoList(FsUserCourseVideo fsUserCourseVideo)
    {
        return fsUserCourseVideoMapper.selectFsUserCourseVideoList(fsUserCourseVideo);
    }

    /**
     * 新增课堂视频
     *
     * @param fsUserCourseVideo 课堂视频
     * @return 结果
     */
    @Override
    public int insertFsUserCourseVideo(FsUserCourseVideo fsUserCourseVideo)
    {
        fsUserCourseVideo.setCreateTime(DateUtils.getNowDate());
        return fsUserCourseVideoMapper.insertFsUserCourseVideo(fsUserCourseVideo);
    }

    /**
     * 修改课堂视频
     *
     * @param fsUserCourseVideo 课堂视频
     * @return 结果
     */
    @Override
    public int updateFsUserCourseVideo(FsUserCourseVideo fsUserCourseVideo)
    {
        fsUserCourseVideo.setUpdateTime(DateUtils.getNowDate());
        return fsUserCourseVideoMapper.updateFsUserCourseVideo(fsUserCourseVideo);
    }

    /**
     * 批量删除课堂视频
     *
     * @param videoIds 需要删除的课堂视频主键
     * @return 结果
     */
    @Override
    public int deleteFsUserCourseVideoByVideoIds(String[] videoIds)
    {
        return fsUserCourseVideoMapper.deleteFsUserCourseVideoByVideoIds(videoIds);
    }

    /**
     * 删除课堂视频信息
     *
     * @param videoId 课堂视频主键
     * @return 结果
     */
    @Override
    public int deleteFsUserCourseVideoByVideoId(String videoId)
    {
        return fsUserCourseVideoMapper.deleteFsUserCourseVideoByVideoId(videoId);
    }

    @Override
    public List<FsUserCourseVideo> selectFsUserCourseVideoListByCourseId(FsUserCourseVideo fsUserCourseVideo) {
        return fsUserCourseVideoMapper.selectFsUserCourseVideoListByCourseId(fsUserCourseVideo);
    }

    @Override
    public List<FsUserCourseVideoListUVO> selectFsUserCourseVideoListUVOByCourseId(FsUserCourseVideoListUParam param) {
        List<FsUserCourseVideoListUVO> list;
        if (param == null || param.getUserId() == null) {
            list = fsUserCourseVideoMapper.selectFsUserCourseVideoListByCourseIdAll(param);

            // 判断是否对前两条记录设置 isVip
            if (!list.isEmpty()) {
                list.stream()
                        .filter(video -> video.getCourseSort() == 1 || video.getCourseSort() == 2)
                        .forEach(video -> video.setIsVip(0));
            }
        } else {
            list = fsUserCourseVideoMapper.selectFsUserCourseVideoListUVOByCourseId(param);
            FsUserCourseOrder order = fsUserCourseOrderMapper.selectFsUserCourseOrderByCourse(param.getUserId(),param.getCourseId());
            if (order!=null&&order.getCreateType()==1){
                list.forEach(item -> item.setIsBuy(1));
            }
            for (FsUserCourseVideoListUVO videoListUVO : list) {
                FsUserCourseStudyLog studyLog = courseStudyLogMapper.selectFsUserCourseStudyLogByUser(param.getUserId(), videoListUVO.getVideoId());
                if (studyLog != null) {
                    videoListUVO.setStudyTime(studyLog.getCurrentTimes());
                    videoListUVO.setTotalTimes(studyLog.getTotalTimes());
                }
            }
            if (!list.isEmpty()) {
                list.stream()
                        .filter(video -> video.getCourseSort() == 1 || video.getCourseSort() == 2)
                        .forEach(video -> {
                            video.setIsVip(0);
                            video.setIsBuy(1);
                        });
            }

        }
        for (FsUserCourseVideoListUVO listUVO : list){
            if (StringUtils.isNotEmpty(listUVO.getPackageJson())){
                List<CoursePackageDTO> packageDTOS = JSON.parseArray(listUVO.getPackageJson(),CoursePackageDTO.class);
                for (CoursePackageDTO packageDTO : packageDTOS){
                    // 将时间按 ":" 分割
                    String[] parts = packageDTO.getDuration().split(":");
                    // 提取小时和分钟
                    int hours = Integer.parseInt(parts[0]);
                    int minutes = Integer.parseInt(parts[1]);
                    // 转换为秒
                    int seconds = hours * 3600 + minutes * 60;
                    packageDTO.setDuration(String.valueOf(seconds));
                }
                listUVO.setPackageJson(JSON.toJSONString(packageDTOS));
            }

        }
        return list;

    }

    @Override
    public Long selectCourseVideoSort(Long courseId) {
        if (fsUserCourseVideoMapper.selectCourseVideoSort(courseId)!=null){
            Long lastSort =  fsUserCourseVideoMapper.selectCourseVideoSort(courseId)+1;
            return lastSort;
        }
        return 1L;
    }

    @Override
    public R updateWatchDuration(FsUserCourseVideoFinishUParam param) {
        //临时短链不做记录
        if (param.getLinkType()!=null && param.getLinkType()==1){
            return R.ok();
        }
        if (param.getIsRoom()!=null&&param.getIsRoom()==1&&param.getQwExternalId()==null){
            return R.ok();
        }

        // 从Redis中获取观看时长
        String redisKey = "h5user:watch:duration:" + param.getQwUserId()+ ":" + param.getQwExternalId() + ":" + param.getVideoId();
        try {
            String durationStr = redisCache.getCacheObject(redisKey);
            Long duration = durationStr != null ? Long.parseLong(durationStr) : 0L;

            // 更新Redis中的观看时长
            if (param.getDuration() != null && param.getDuration() > duration) {
                //24小时过期
                redisCache.setCacheObject(redisKey, param.getDuration().toString(),2,TimeUnit.HOURS);
            }
            updateHeartbeat(param);
            return R.ok();
        }catch (Exception e){
            e.printStackTrace();
            logger.error("更新时长失败：{}",redisKey,e.getMessage());
            return R.error();
        }

    }

    //更新心跳时间
    public void updateHeartbeat(FsUserCourseVideoFinishUParam param) {
        String redisKey = "h5user:watch:heartbeat:" + param.getQwUserId()+ ":" + param.getQwExternalId() + ":" + param.getVideoId();
        redisCache.setCacheObject(redisKey, LocalDateTime.now().toString());
        // 设置 Redis 记录的过期时间（例如 5 分钟）
        redisCache.expire(redisKey, 300, TimeUnit.SECONDS);
    }

    @Override
    @Transactional
    public R isAddKf(FsUserCourseVideoAddKfUParam param) {
        logger.info("zyp \n【判断添加客服】：{}",param);
        //查询用户
        FsUser fsUser = fsUserMapper.selectFsUserByUserId(param.getUserId());
        //用户不存在唤起重新授权
        if (fsUser==null){
            return R.error(504,"未授权");
        }

        String msg = "<div style=\"color: red;margin-bottom: 15px;font-weight: bold;\">本课程为会员独享<br>请长按二维码</div>\n" +
                "\t\t\t\t\t<div style=\"color: #999;font-size: 14px;font-weight: bold;\">添加伴学助手免费领取会员权限</div>";

        Integer isRoom = param.getIsRoom();

        // 处理逻辑
        if (isRoom == null || isRoom == 0) {
            // 当 isRoom 为 null 或 0 时走 handleExt
            return handleExt(param,msg);
        } else if (isRoom == 1) {
            // 当 isRoom 为 1 时走 handleRoom
            return handleRoom(param,fsUser);
        } else {
            // 非法参数
            logger.warn("非法参数 isRoom: {}", isRoom);
            return R.error("参数错误！");
        }

    }

    //群聊逻辑
    private R handleRoom(FsUserCourseVideoAddKfUParam param,FsUser user) {
        if (user.getQwExtId()!=null){
            param.setQwExternalId(user.getQwExtId());
            //查询是否有添加客服
            QwExternalContact externalContact = qwExternalContactMapper.selectQwExternalContactById(param.getQwExternalId());
            if (externalContact==null){
                return R.error("客户不存在！");
            }
            if (!externalContact.getQwUserId().equals(Long.parseLong(param.getQwUserId()))){
                logger.error("zyp \n【无权观看参数】：{}",param);
                return R.error("无权限观看，添加群主非本群主");
            }
            FsCourseWatchLog log = courseWatchLogMapper.getWatchCourseVideoByExt(param.getQwExternalId(), param.getVideoId(),param.getQwUserId());
            if (log==null){
                createWatchLog(param);
            }
            return R.ok().put("qwExternalId",user.getQwExtId());
        }
        return R.ok();
    }

    private void createWatchLog(FsUserCourseVideoAddKfUParam param) {
        FsCourseWatchLog log = new FsCourseWatchLog();
        BeanUtils.copyProperties(param,log);
        log.setQwExternalContactId(param.getQwExternalId());
        log.setSendType(2);
        log.setDuration(0L);
        log.setCreateTime(new Date());
        log.setLogType(3);
        courseWatchLogMapper.insertFsCourseWatchLog(log);
    }

    private R handleExt(FsUserCourseVideoAddKfUParam param,String msg){
        if (param.getLinkType()!=null&&param.getLinkType()==1){
            if (param.getLinkId()!=null){
                // 从数据库中查找短链对应的真实链接
                FsCourseLink courseLink = courseLinkMapper.selectFsCourseLinkByLinkId(param.getLinkId());
                if (courseLink != null) {
                    // 获取当前时间
                    Date currentTime = new Date();
                    // 获取链接的更新时间（假设这个字段代表过期时间）
                    Date updateTime = courseLink.getUpdateTime();

                    // 判断是否过期
                    if (currentTime.after(updateTime)) {
                        // 链接已过期
                        return R.error("链接已过期");
                    }else {
                        return R.ok();
                    }
                }
            }
            return R.error("链接过期");
        }



        FsCourseWatchLog log = courseWatchLogMapper.getWatchCourseVideoByExt(param.getQwExternalId(), param.getVideoId(),param.getQwUserId());
        if (log==null ){
            return addCustomerService(param.getQwUserId(),msg);
        }

        //查询是否有添加客服
        QwExternalContact externalContact = qwExternalContactMapper.selectQwExternalContactById(param.getQwExternalId());

        //用小程序id查询外部联系人
        List<QwExternalContact> qwExternalContacts = qwExternalContactMapper.selectQwExternalContactByMiniUserId(param.getUserId());


        //如果查不出来客户信息，加好友
        if(externalContact==null){
            return addCustomerService(param.getQwUserId(),msg);
        }

        //判断外部联系人有没有绑定userId
        if (externalContact.getFsUserId()!=null){
            //有客户有小程序id  但 登录的小程序id和根据外部联系人id查出来的小程序id不一致
            if (!externalContact.getFsUserId().equals(param.getUserId())) {
                return addCustomerService(param.getQwUserId(),msg);
            }
            //匹配客户公司id
            if (qwExternalContacts.stream().noneMatch(contact -> contact.getCorpId().equals(param.getCorpId()))){
                return addCustomerService(param.getQwUserId(),msg);
            }

            //看课记录中userId为0绑定userId
            if (log.getUserId()==null||log.getUserId().equals(0L) || !log.getUserId().equals(param.getUserId())){
                log.setUserId(param.getUserId());
            }
            log.setUpdateTime(new Date());
            courseWatchLogMapper.updateFsCourseWatchLog(log);
            return R.ok();

        }else {
            //没绑定fsUser直接绑定fsUser
            QwExternalContact contact = new QwExternalContact();
            contact.setId(param.getQwExternalId());
            contact.setFsUserId(param.getUserId());
            qwExternalContactMapper.updateQwExternalContact(contact);
            FsUser user = new FsUser();
            user.setUserId(param.getUserId());
            user.setIsAddQw(1);
            user.setQwExtId(param.getQwExternalId());
            fsUserMapper.updateFsUser(user);

            List<String> list= sopUserLogsInfoMapper.selectSopUserLogsInfoByExtId(contact.getId());
            if (list!=null&& !list.isEmpty()){
                sopUserLogsInfoMapper.updateSopUserLogsInfoFsUserIdById(list,param.getUserId());
            }
            //绑定上之后 更新观看记录
            //看课记录中userId为0绑定userId
            if (log.getUserId()==null||log.getUserId().equals(0L) || !log.getUserId().equals(param.getUserId())){
                log.setUserId(param.getUserId());
            }

            log.setUpdateTime(new Date());
            courseWatchLogMapper.updateFsCourseWatchLog(log);
            return R.ok();
        }
    }

    private R addCustomerService(String qwUserById,String msg){
        String contactWay = "";
        QwUser qwUser = qwUserMapper.selectQwUserById(Long.parseLong(qwUserById));
        if (qwUser==null){
            return R.error("客服不存在");
        }
        if (StringUtils.isNotEmpty(qwUser.getContactWay())){
            contactWay = qwUser.getContactWay();
        }
        else {
            String qwUserId = "[\"" + qwUser.getQwUserId() + "\"]";
            List<String> users = JSON.parseArray(qwUserId, String.class);
            QwAddContactWayParam qwAddContactWayParam = new QwAddContactWayParam();
            qwAddContactWayParam.setType(1);
            qwAddContactWayParam.setScene(2);
            qwAddContactWayParam.setUser(users);
            qwAddContactWayParam.setSkip_verify(true);
            QwAddContactWayResult qwAddContactWayResult = qwApiService.addContactWay(qwAddContactWayParam, qwUser.getCorpId());
            if (qwAddContactWayResult.getErrcode() == 0) {
                qwUser.setContactWay(qwAddContactWayResult.getQr_code());
                qwUser.setConfigId(qwAddContactWayResult.getConfig_id());
                qwUserMapper.updateQwUser(qwUser);
                contactWay = qwUser.getContactWay();
            } else {
                return R.error("请联系管理员>>>"+qwAddContactWayResult.getErrmsg());
            }
        }
        return R.error(400,msg).put("qrcode",contactWay);
    }

    @Override
    public List<FsUserCourseVideoVO> selectFsUserCourseVideoListByCourseIdAndCompany(FsUserCourseVideoParam fsUserCourseVideo) {
        return fsUserCourseVideoMapper.selectFsUserCourseVideoListByCourseIdAndCompany(fsUserCourseVideo);
    }

    @Override
    public R updateFsUserCourseVideoCompanyRedPacket(FsUserCourseVideoParam fsUserCourseVideo) {
        fsUserCourseVideoRedPackageMapper.insertOrUpdateFsUserCourseVideoRedPackage(fsUserCourseVideo);
        return R.ok();
    }


    @Transactional
    @Override
    public R getInternetTraffic(FsUserCourseVideoFinishUParam param) {
        try {
            FsCourseTrafficLog trafficLog = new FsCourseTrafficLog();
            trafficLog.setQwExternalContactId(param.getQwExternalId() != null ? param.getQwExternalId() : 0L);
            trafficLog.setCreateTime(new Date());
            BeanUtils.copyProperties(param, trafficLog);

            FsUserCourseVideo video = fsUserCourseVideoMapper.selectFsUserCourseVideoByVideoId(param.getVideoId());
            if (video == null) {
                return R.error("视频不存在");
            }

            // 计算流量
            BigDecimal result = param.getBufferRate().divide(new BigDecimal("100"), 4, RoundingMode.HALF_UP);
            BigDecimal longAsBigDecimal = BigDecimal.valueOf(video.getFileSize());
            long roundedResult = result.multiply(longAsBigDecimal).setScale(0, RoundingMode.HALF_UP).longValue();
            trafficLog.setInternetTraffic(roundedResult);

            // 处理 UUID 为空的情况
            if (StringUtils.isNotEmpty(trafficLog.getUuId())) {
                // 直接插入或更新
//                logger.error("zyp \n【插入或更新流量】：{}",trafficLog);
                fsCourseTrafficLogMapper.insertOrUpdateTrafficLog(trafficLog);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("zyp \n【插入或更新流量失败】：{}",e.getMessage());
            return R.error();
        }
        return R.ok();
    }


    @Override
    public R getIntegralByH5Video(FsUserCourseVideoFinishUParam param) {
        //临时短链不做处理
        if (param.getLinkType()!=null&&param.getLinkType()==1){
            return R.ok();
        }
        FsCourseWatchLog log = courseWatchLogMapper.getWatchCourseVideo(param.getUserId(),param.getVideoId(),param.getQwUserId(), param.getQwExternalId());
        if (log==null){
            return R.error("无记录");
        }
        if (log.getLogType()==2){
            return R.error("已存在完课记录");
        }
        if (log.getLogType()==1){
            FsUserCourseVideo video = fsUserCourseVideoMapper.selectFsUserCourseVideoByVideoId(param.getVideoId());
            if (video==null){
                return R.error("课程视频不存在！");
            }
            FsUser user = fsUserMapper.selectFsUserByUserId(param.getUserId());
            if (user!=null){
                //判断该视频可增加积分的此时 （每十分钟增加积分）
                Long count = video.getDuration()/600;
                Long getIntegralCount = fsUserIntegralLogsMapper.selectH5VideoIntegralCount(param.getUserId(), param.getVideoId());
                if (getIntegralCount.equals(count)){
                    return R.error("该课堂或积分已达限制！");
                }
                String json = configService.selectConfigByKey("course.config");
                CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
                //增加积分
                FsUser userMap=new FsUser();
                userMap.setUserId(user.getUserId());
                userMap.setIntegral(user.getIntegral()+config.getVideoIntegral());
                fsUserMapper.updateFsUser(userMap);
                FsUserIntegralLogs integralLogs = new FsUserIntegralLogs();
                integralLogs.setIntegral(config.getVideoIntegral().longValue());
                integralLogs.setUserId(user.getUserId());
                integralLogs.setBalance(userMap.getIntegral());
                integralLogs.setLogType(16);
                integralLogs.setBusinessId(log.getLogId().toString());
                integralLogs.setCreateTime(new Date());
                fsUserIntegralLogsMapper.insertFsUserIntegralLogs(integralLogs);

                FsCourseRedPacketLog redPacketLog = new FsCourseRedPacketLog();
                redPacketLog.setCourseId(log.getCourseId());
                redPacketLog.setOutBatchNo(integralLogs.getId().toString());
                redPacketLog.setCompanyId(log.getCompanyId());
                redPacketLog.setUserId(log.getUserId());
                redPacketLog.setVideoId(log.getVideoId());
                redPacketLog.setStatus(1);
                redPacketLog.setQwUserId(log.getQwUserId() != null ? log.getQwUserId() : null );
                redPacketLog.setCompanyUserId(log.getCompanyUserId());
                redPacketLog.setCreateTime(new Date());
                redPacketLog.setAmount(BigDecimal.valueOf(config.getVideoIntegral()).divide(BigDecimal.valueOf(1000)));
                redPacketLog.setRemark("点播看课获得积分转");
                redPacketLog.setWatchLogId(log.getLogId() !=null ? log.getLogId() : null);
                redPacketLogMapper.insertFsCourseRedPacketLog(redPacketLog);
                return R.ok();
            }
        }
        return R.error();
    }


    @Override
    @Transactional
    public R sendReward(FsCourseSendRewardUParam param) {
        // 获取用户信息
        FsUser user = fsUserMapper.selectFsUserByUserId(param.getUserId());
//        if (StringUtils.isEmpty(user.getMpOpenId())){
//            return R.error("未识别到领取信息");
//        }
        FsCourseWatchLog log = new FsCourseWatchLog();

        // 根据链接类型判断是否已发放奖励
        if (param.getLinkType() != null && param.getLinkType() == 1) {
            FsCourseRedPacketLog packetLog = redPacketLogMapper.selectFsCourseRedPacketLogByTemporary(param.getVideoId(), param.getUserId());
            if (packetLog != null) {
                return R.error("奖励已发放");
            }
        } else {
            log = courseWatchLogMapper.getWatchCourseVideo(param.getUserId(), param.getVideoId(), param.getQwUserId(), param.getQwExternalId());
            if (log == null) {
                return R.error("无记录");
            }
            if (log.getRewardType() != null) {
                return R.error("奖励已发放");
            }
        }

        // 获取视频信息
        FsUserCourseVideo video = fsUserCourseVideoMapper.selectFsUserCourseVideoByVideoId(param.getVideoId());

        // 获取配置信息
        String json = configService.selectConfigByKey("course.config");
        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);

        // 根据奖励类型发放不同奖励
        switch (config.getRewardType()) {
            // 红包奖励
            case 1:
                return sendRedPacketReward(param, user, log, video, config);
            // 积分奖励
            case 2:
                return sendIntegralReward(param,user, log, config);
            default:
                return R.error("参数错误！");
        }
    }

    /**
     * 发放红包奖励
     *
     * @param param 请求参数
     * @param user 用户信息
     * @param log 观看日志
     * @param video 视频信息
     * @param config 配置信息
     * @return 处理结果
     */
    private R sendRedPacketReward(FsCourseSendRewardUParam param, FsUser user, FsCourseWatchLog log, FsUserCourseVideo video, CourseConfig config) {
        // 确定红包金额
        BigDecimal amount = BigDecimal.ZERO;
        FsUserCourseVideoRedPackage redPackage = fsUserCourseVideoRedPackageMapper.selectRedPacketByCompanyId(param.getVideoId(), param.getCompanyId());

        if (redPackage != null) {
            amount = redPackage.getRedPacketMoney();
        } else if (video != null) {
            amount = new BigDecimal(video.getRedPacketMoney());
        }

        // 准备发送红包参数
        WxSendRedPacketParam packetParam = new WxSendRedPacketParam();
        packetParam.setOpenId(user.getMpOpenId());
        // 来源是小程序切换openId
        if (param.getSource() == 2) {
            packetParam.setOpenId(user.getCourseMaOpenId());
        }
        packetParam.setAmount(amount);
        packetParam.setSource(param.getSource());
        packetParam.setRedPacketMode(config.getRedPacketMode());
        packetParam.setCompanyId(param.getCompanyId());


        // 发送红包
        R sendRedPacket = paymentService.sendRedPacket(packetParam);
        if (sendRedPacket.get("code").equals(200)) {
            FsCourseRedPacketLog redPacketLog = new FsCourseRedPacketLog();
            TransferBillsResult transferBillsResult;
            if (sendRedPacket.get("isNew").equals(1)){
                transferBillsResult = (TransferBillsResult)sendRedPacket.get("data");
                redPacketLog.setOutBatchNo(transferBillsResult.getOutBillNo());
            }else {
                redPacketLog.setOutBatchNo(sendRedPacket.get("orderCode").toString());
            }
            // 添加红包记录
            redPacketLog.setCourseId(param.getCourseId());
            redPacketLog.setCompanyId(param.getCompanyId());
            redPacketLog.setUserId(param.getUserId());
            redPacketLog.setVideoId(param.getVideoId());
            redPacketLog.setStatus(0);
            redPacketLog.setQwUserId(param.getQwUserId() != null ? param.getQwUserId() : null);
            redPacketLog.setCompanyUserId(param.getCompanyUserId());
            redPacketLog.setCreateTime(new Date());
            redPacketLog.setAmount(amount);
            redPacketLog.setWatchLogId(log.getLogId() != null ? log.getLogId() : null);
            redPacketLogMapper.insertFsCourseRedPacketLog(redPacketLog);

            // 更新观看记录的奖励类型
            if (param.getLinkType() == null || param.getLinkType() == 0) {
                log.setRewardType(config.getRewardType());
                courseWatchLogMapper.updateFsCourseWatchLog(log);
            }
            return sendRedPacket;
        } else {
            return R.error("奖励发送失败，请联系客服");
        }
    }

    /**
     * 发放积分奖励
     *
     * @param user 用户信息
     * @param log 观看日志
     * @param config 配置信息
     * @return 处理结果
     */
    private R sendIntegralReward(FsCourseSendRewardUParam param,FsUser user, FsCourseWatchLog log, CourseConfig config) {
        // 更新用户积分
        FsUser userMap=new FsUser();
        userMap.setUserId(user.getUserId());
        userMap.setIntegral(user.getIntegral()+config.getAnswerIntegral());
        fsUserMapper.updateFsUser(userMap);
        FsUserIntegralLogs integralLogs = new FsUserIntegralLogs();
        integralLogs.setIntegral(config.getAnswerIntegral().longValue());
        integralLogs.setUserId(user.getUserId());
        integralLogs.setBalance(userMap.getIntegral());
        integralLogs.setLogType(17);
        integralLogs.setBusinessId(StringUtils.isNotEmpty(log.getLogId().toString()) ? log.getLogId().toString() : null);
        integralLogs.setCreateTime(new Date());
        fsUserIntegralLogsMapper.insertFsUserIntegralLogs(integralLogs);
        // 更新观看记录的奖励类型
        if (param.getLinkType() == null || param.getLinkType() == 0) {
            log.setRewardType(config.getRewardType());
            courseWatchLogMapper.updateFsCourseWatchLog(log);
        }
        return R.ok("奖励发放成功");
    }


    @Override
    @Transactional
    public R sendRewardNew(FsCourseSendRewardUParam param) {
        FsUser user = fsUserMapper.selectFsUserByUserId(param.getUserId());
        if (StringUtils.isEmpty(user.getMpOpenId())){
            return R.error("未识别到领取信息");
        }
        FsCourseWatchLog log = new FsCourseWatchLog();

        //判断链接类型
        if (param.getLinkType()!=null&&param.getLinkType()==1){
            FsCourseRedPacketLog packetLog = redPacketLogMapper.selectFsCourseRedPacketLogByTemporary(param.getVideoId(),param.getUserId());
            if (packetLog!=null){
                return R.error("奖励已发放");
            }
        }else {
            log = courseWatchLogMapper.getWatchCourseVideo(param.getUserId(),param.getVideoId(),param.getQwUserId(),param.getQwExternalId());
            if (log==null){
                return R.error("无记录");
            }
            if (log.getRewardType()!=null){
                return R.error("奖励已发放");
            }
        }

        FsUserCourseVideo video = fsUserCourseVideoMapper.selectFsUserCourseVideoByVideoId(param.getVideoId());
        //发放奖励
        switch (param.getRewardType()){
            //红包奖励
            case 1:
                BigDecimal amount = BigDecimal.ZERO;
                FsUserCourseVideoRedPackage redPackage = fsUserCourseVideoRedPackageMapper.selectRedPacketByCompanyId(param.getVideoId(), param.getCompanyId());
                WxSendRedPacketParam packetParam = new WxSendRedPacketParam();

                if (redPackage!=null){
                    amount = redPackage.getRedPacketMoney();
                }else if (video!=null){
                    amount = new BigDecimal(video.getRedPacketMoney());
                }
                packetParam.setOpenId(user.getMpOpenId());
                packetParam.setAmount(amount);
                R sendRedPacket = paymentService.sendRedPacketV3(packetParam);
                if (sendRedPacket.get("code").equals(200)){
                    TransferBillsResult transferBillsResult = (TransferBillsResult)sendRedPacket.get("data");
                    //添加红包记录
                    FsCourseRedPacketLog redPacketLog = new FsCourseRedPacketLog();
                    redPacketLog.setCourseId(param.getCourseId());
                    redPacketLog.setOutBatchNo(transferBillsResult.getOutBillNo());
                    redPacketLog.setCompanyId(param.getCompanyId());
                    redPacketLog.setUserId(param.getUserId());
                    redPacketLog.setVideoId(param.getVideoId());
                    redPacketLog.setStatus(0);
                    redPacketLog.setQwUserId(param.getQwUserId() != null ? param.getQwUserId() : null );
                    redPacketLog.setCompanyUserId(param.getCompanyUserId());
                    redPacketLog.setCreateTime(new Date());
                    redPacketLog.setAmount(amount);
                    redPacketLog.setWatchLogId(log.getLogId() !=null ? log.getLogId() : null);
                    redPacketLogMapper.insertFsCourseRedPacketLog(redPacketLog);
                    if (param.getLinkType()==null || param.getLinkType()==0){
                        log.setRewardType(param.getRewardType());
                        courseWatchLogMapper.updateFsCourseWatchLog(log);
                    }
                    return R.ok("奖励发放成功").put("package",transferBillsResult.getPackageInfo());
                }else {
                    return R.error("奖励发送失败，请联系客服");
                }
                //积分奖励
            case 2:
                String json = configService.selectConfigByKey("course.config");
                CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
                //增加积分
                FsUser userMap=new FsUser();
                userMap.setUserId(user.getUserId());
                userMap.setIntegral(user.getIntegral()+config.getAnswerIntegral());
                fsUserMapper.updateFsUser(userMap);
                FsUserIntegralLogs integralLogs = new FsUserIntegralLogs();
                integralLogs.setIntegral(config.getAnswerIntegral().longValue());
                integralLogs.setUserId(user.getUserId());
                integralLogs.setBalance(userMap.getIntegral());
                integralLogs.setLogType(17);
                integralLogs.setBusinessId(StringUtils.isNotEmpty(log.getLogId().toString()) ? log.getLogId().toString() : null);
                integralLogs.setCreateTime(new Date());
                fsUserIntegralLogsMapper.insertFsUserIntegralLogs(integralLogs);
                if (param.getLinkType()==null || param.getLinkType()==0 ){
                    log.setRewardType(param.getRewardType());
                    courseWatchLogMapper.updateFsCourseWatchLog(log);
                    //转换红包
                    FsCourseRedPacketLog redPacketLog = new FsCourseRedPacketLog();
                    redPacketLog.setCourseId(param.getCourseId());
                    redPacketLog.setOutBatchNo(integralLogs.getId().toString());
                    redPacketLog.setCompanyId(param.getCompanyId());
                    redPacketLog.setUserId(param.getUserId());
                    redPacketLog.setVideoId(param.getVideoId());
                    redPacketLog.setStatus(1);
                    redPacketLog.setQwUserId(param.getQwUserId() != null ? param.getQwUserId() : null );
                    redPacketLog.setCompanyUserId(param.getCompanyUserId());
                    redPacketLog.setCreateTime(new Date());
                    redPacketLog.setAmount(BigDecimal.valueOf(config.getAnswerIntegral()).divide(BigDecimal.valueOf(1000)));
                    redPacketLog.setRemark("点播答题领取积分转");
                    redPacketLog.setWatchLogId(log.getLogId() !=null ? log.getLogId() : null);
                    redPacketLogMapper.insertFsCourseRedPacketLog(redPacketLog);
                }
                return R.ok("奖励发放成功");
            default:
                return R.error("参数错误！");
        }
    }

    @Override
    public List<FsUserCourseVideoPageListVO> pageListCourseVideo(UserCourseVideoPageParam param) {
        return fsUserCourseVideoMapper.selectFsUserCourseVideoPageList(param);
    }

    @Override
    public ResponseResult<FsUserCourseVideoDetailsVO> getVideoDetails(Long videoId) {
        FsUserCourseVideo fsUserCourseVideo = fsUserCourseVideoMapper.selectFsUserCourseVideoByVideoId(videoId);
        FsUserCourseVideoDetailsVO fsUserCourseVideoDetailsVO = new FsUserCourseVideoDetailsVO();
        BeanUtils.copyProperties(fsUserCourseVideo, fsUserCourseVideoDetailsVO);

        // 获取课程相关的题库
        String questionBankId = fsUserCourseVideo.getQuestionBankId();
        List<FsUserVideoQuestionVO> questionList = Collections.emptyList();
        if (StringUtils.isNotEmpty(questionBankId)) {
            String[] questionBankIds = questionBankId.split(",");
            List<FsCourseQuestionBank> fsCourseQuestionBanks = courseQuestionBankMapper.selectFsCourseQuestionBankByIdVO(questionBankIds);
            questionList = fsCourseQuestionBanks.stream().map(v -> {
                FsUserVideoQuestionVO fsUserVideoQuestionVO = new FsUserVideoQuestionVO();
                BeanUtils.copyProperties(v, fsUserVideoQuestionVO);
                return fsUserVideoQuestionVO;
            }).collect(Collectors.toList());
        }

        fsUserCourseVideoDetailsVO.setQuestionBankList(questionList);
        return ResponseResult.ok(fsUserCourseVideoDetailsVO);
    }

    @Autowired
    SopUserLogsInfoMapper sopUserLogsInfoMapper;

    @Override
    public R registerCourse(FsUserCourseRegisterParam param,FsUser fsUser) {
        QwExternalContact qwExternalContact = qwExternalContactMapper.selectQwExternalContactById(param.getQwExternalId());
        if (qwExternalContact==null){
            return R.error("注册信息错误");
        }
        FsUser u = new FsUser();
        u.setUserId(param.getUserId());
        u.setIsAddQw(1);
        u.setQwExtId(param.getQwExternalId());
        fsUserMapper.updateFsUser(u);
        QwExternalContact qw = new QwExternalContact();
        qw.setFsUserId(fsUser.getUserId());
        qw.setId(qwExternalContact.getId());
        qwExternalContactMapper.updateById(qw);
        List<String> list= sopUserLogsInfoMapper.selectSopUserLogsInfoByExtId(qwExternalContact.getId());
        if (list!=null&& !list.isEmpty()){
            sopUserLogsInfoMapper.updateSopUserLogsInfoFsUserIdById(list,param.getUserId());
        }
        return R.ok();
    }

    @Override
    public List<FsUserVideoListVO> getListCourseVideo(UserCourseVideoPageParam param) {
        List<FsUserCourseVideoPageListVO> list = fsUserCourseVideoMapper.selectFsUserCourseVideoPageList(param);
        return list.stream().map(v -> {
            FsUserVideoListVO videoListVO = new FsUserVideoListVO();
            BeanUtils.copyProperties(v, videoListVO);
            return videoListVO;
        }).collect(Collectors.toList());
    }


}
