package com.fjhx.service.video.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.base.BaseEntity;
import com.fjhx.entity.FileInfo;
import com.fjhx.entity.video.VideoInfo;
import com.fjhx.mapper.video.VideoInfoMapper;
import com.fjhx.params.video.VideoInfoVo;
import com.fjhx.service.video.VideoClassifyService;
import com.fjhx.service.video.VideoInfoService;
import com.fjhx.utils.Assert;
import com.fjhx.utils.FileClientUtil;
import com.fjhx.utils.WrapperUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2022-08-08
 */
@Service
public class VideoInfoServiceImpl extends ServiceImpl<VideoInfoMapper, VideoInfo> implements VideoInfoService {

    @Autowired
    private VideoClassifyService videoClassifyService;

    @Override
    public Page<Map<String, Object>> getPage(Map<String, String> condition) {

        QueryWrapper<VideoInfo> wrapper = Wrappers.query();

        WrapperUtil.init(condition, wrapper)
                .keyword("title")
                .createTimeDesc();

        wrapper.lambda().select(
                BaseEntity::getId, VideoInfo::getTitle, VideoInfo::getStatus, VideoInfo::getDuration
                , VideoInfo::getSize, BaseEntity::getCreateTime, BaseEntity::getUpdateTime
        );

        String classifyId = condition.get("classifyId");
        if (ObjectUtil.isNotEmpty(classifyId)) {
            List<Long> childrenIdList = videoClassifyService.getChildrenIdList(Long.valueOf(classifyId));
            wrapper.lambda().in(VideoInfo::getVideoClassifyId, childrenIdList);
        }

        // 赋值视频地址
        Page<Map<String, Object>> page = pageMaps(createPageMap(condition), wrapper);
        List<Map<String, Object>> records = page.getRecords();

        if (records.size() == 0) {
            return page;
        }

        List<Long> idList = records.stream().map(item -> (Long) item.get("id")).collect(Collectors.toList());

        Map<Long, FileInfo> fileInfoMap = FileClientUtil.getFileInfoMap(idList);

        for (Map<String, Object> record : records) {
            Long id = (Long) record.get("id");

            FileInfo fileInfo = fileInfoMap.get(id);
            if (fileInfo != null) {
                record.put("videoUrl", fileInfo.getFilePath());
            }

            // kb转m
            Long size = (Long) record.get("size");
            record.put("size", size / 1024 + "M");

            // 秒转时分秒
            Long duration = (Long) record.get("duration");
            StringBuilder durationSB = new StringBuilder();
            long h = duration / 60 / 60;
            if (h > 0) {
                durationSB.append(h).append("时");
            }
            long m = duration / 60 % 60;
            if (h > 0 || m > 0) {
                durationSB.append(m).append("分");
            }
            long s = duration % 60;
            durationSB.append(s).append("秒");

            record.put("duration", durationSB.toString());

        }

        return page;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(VideoInfoVo videoInfoVo) {

        setVideo(videoInfoVo);

        // TODO 类型未定，目前先赋值已发布
        videoInfoVo.setStatus(2);

        // 播放量
        videoInfoVo.setPlaybackVolume(0L);

        // 变更分类视频数量
        updateClassifyVideoNum(null, videoInfoVo.getVideoClassifyId(), videoInfoVo.getVideoNum());

        save(videoInfoVo);

        // 添加文件
        FileClientUtil.bindingFile(videoInfoVo.getId(), videoInfoVo.getFileInfoList());

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(VideoInfoVo videoInfoVo) {

        setVideo(videoInfoVo);

        // 变更分类视频数量
        updateClassifyVideoNum(videoInfoVo.getId(), videoInfoVo.getVideoClassifyId(), videoInfoVo.getVideoNum());

        updateById(videoInfoVo);

        // 编辑文件
        FileClientUtil.againBindingFile(videoInfoVo.getId(), videoInfoVo.getFileInfoList());

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(VideoInfoVo videoInfoVo) {
        Long id = videoInfoVo.getId();

        // 变更分类视频数量
        updateClassifyVideoNum(videoInfoVo.getId(), null, 0);

        removeById(id);

        // 删除文件
        FileClientUtil.relieveBindingFile(id);

    }

    @Override
    public Map<String, Object> details(VideoInfoVo videoInfoVo) {
        Long id = videoInfoVo.getId();
        Assert.notEmpty(id, "id不能为空");

        Map<String, Object> map = getMap(Wrappers.<VideoInfo>lambdaQuery().eq(BaseEntity::getId, id));
        List<FileInfo> fileInfoList = FileClientUtil.getFileInfoList(id);

        map.put("fileInfoList", fileInfoList);

        return map;
    }

    /**
     * 保存视频信息
     */
    private void setVideo(VideoInfoVo videoInfoVo) {
        List<FileInfo> fileInfoList = videoInfoVo.getFileInfoList();

        if (ObjectUtil.isEmpty(fileInfoList)) {
            videoInfoVo.setSize(0L);
            videoInfoVo.setDuration(0L);
            videoInfoVo.setVideoNum(0);
            return;
        }

        // 视频大小
        Long size = fileInfoList.stream().mapToLong(FileInfo::getFileSize).sum();
        videoInfoVo.setSize(size);

        // 视频时长
        Long duration = fileInfoList.stream().mapToLong(FileInfo::getDuration).sum();
        videoInfoVo.setDuration(duration);

        // 视频数量
        videoInfoVo.setVideoNum(fileInfoList.size());
    }

    /**
     * 修改分类保存的视频数量
     */
    private void updateClassifyVideoNum(Long id, Long classifyId, Integer videoNum) {
        if (id == null) {
            videoClassifyService.updateVideoNum(classifyId, 0, classifyId, videoNum);
            return;
        }

        VideoInfo byId = getById(id);
        videoClassifyService.updateVideoNum(byId.getVideoClassifyId(), byId.getVideoNum(), classifyId, videoNum);
    }

}
