package cn.iocoder.byzs.module.aicourse.service.aiCourse;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.iocoder.byzs.framework.common.pojo.PageResult;
import cn.iocoder.byzs.framework.common.util.object.BeanUtils;
import cn.iocoder.byzs.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.byzs.module.aicourse.controller.admin.aiCourse.vo.AiCoursePageReqVO;
import cn.iocoder.byzs.module.aicourse.controller.admin.aiCourse.vo.AiCourseRespVO;
import cn.iocoder.byzs.module.aicourse.controller.admin.aiCourse.vo.AiCourseSaveReqVO;
import cn.iocoder.byzs.module.aicourse.dal.dataobject.aiCourse.AiCourseDO;
import cn.iocoder.byzs.module.aicourse.dal.dataobject.aiCourseProgress.AiCourseProgressDO;
import cn.iocoder.byzs.module.aicourse.dal.dataobject.aiCourseType.AiCourseTypeDO;
import cn.iocoder.byzs.module.aicourse.dal.mysql.aiCourse.AiCourseMapper;
import cn.iocoder.byzs.module.aicourse.dal.mysql.aiCourseProgress.AiCourseProgressMapper;
import cn.iocoder.byzs.module.aicourse.dal.mysql.aiCourseType.AiCourseTypeMapper;
import cn.iocoder.byzs.module.infra.dal.dataobject.file.FileDO;
import cn.iocoder.byzs.module.infra.framework.file.core.client.FileClient;
import cn.iocoder.byzs.module.infra.service.file.FileConfigService;
import cn.iocoder.byzs.module.infra.service.file.FileServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

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

import static cn.iocoder.byzs.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.byzs.module.aicourse.enums.ErrorCodeConstants.*;

/**
 * 课程 Service 实现类
 *
 * @author lyb
 */
@Service
@Validated
public class AiCourseServiceImpl implements AiCourseService {

    @Resource
    private AiCourseMapper aiCourseMapper;
    @Resource
    private AiCourseTypeMapper aiCourseTypeMapper;
    @Resource
    private FileServiceImpl fileService;
    @Resource
    private FileConfigService fileConfigService;
    @Resource
    private AiCourseProgressMapper aiCourseProgressMapper;

    @Override
    public Long createAiCourse(AiCourseSaveReqVO createReqVO) {
        // 插入
        AiCourseDO blockly = BeanUtils.toBean(createReqVO, AiCourseDO.class);
        aiCourseMapper.insert(blockly);

        if (blockly.getAcContentType().equals("video")) {
            getSelf().asymcVideoFfmpeg(blockly);
        }
        // 返回
        return blockly.getId();
    }

    @Override
    public void updateAiCourse(AiCourseSaveReqVO updateReqVO) {
        // 校验存在
        AiCourseDO blocklyDO = validateAiCourseExists(updateReqVO.getId());
        // 更新
        AiCourseDO updateObj = BeanUtils.toBean(updateReqVO, AiCourseDO.class);
        aiCourseMapper.updateById(updateObj);

        //同步进度表中的课程类型
        if (!blocklyDO.getAcType().equals(updateObj.getAcType())) {
            AiCourseTypeDO blocklyTypeDO = aiCourseTypeMapper.selectById(updateObj.getAcType());
            // 使用条件更新，将brpCtId等于旧课程类型ID的记录更新为新课程类型ID
            aiCourseProgressMapper.update(new AiCourseProgressDO().setBrpCtId(updateObj.getAcType()).setBrpZtId(blocklyTypeDO.getCtParentId()),
                                         new LambdaQueryWrapperX<AiCourseProgressDO>().eq(AiCourseProgressDO::getBrpCtId, blocklyDO.getAcType()));
        }

        if (updateObj.getAcContentType().equals("video")) {
            getSelf().asymcVideoFfmpeg(updateObj);
        }
    }

    @Async
    public void asymcVideoFfmpeg(AiCourseDO blockly) {
        //只对mp4文件进行处理
        String blocklyVideoPath = blockly.getAcContent();
        String ext = blocklyVideoPath.substring(blocklyVideoPath.lastIndexOf("."));
        if (StrUtil.isBlank(ext) || ext.equals(".m3u8")) {
            return;
        }

        //获取相对文件路径
        FileDO fileDO= fileService.getFilePathByUrl(blockly.getAcContent());
        if (fileDO == null || fileDO.getPath() == null) {
            return;
        }

        //切片
        FileClient client = fileConfigService.getMasterFileClient();
        String m3u8Path = client.ffmpegHts(fileDO.getPath());
        if(StrUtil.isNotEmpty(m3u8Path)){
            aiCourseMapper.updateById(new AiCourseDO().setId(blockly.getId()).setAcContent(m3u8Path));
            fileDO.setUrl(m3u8Path);
            fileService.updateFileById(fileDO);

            // 从文件存储器中删除【暂时不删除mp4文件，删除时需要同步更改fileDo中path的相对路径更改成m3u8文件】
//            try {
//                client.delete(blocklyVideoPath);
//            } catch (Exception e) {
//                throw new RuntimeException(e);
//            }
        }
    }

    @Override
    public void deleteAiCourse(Long id) {
        // 校验存在
        validateAiCourseExists(id);
        // 删除
        aiCourseMapper.deleteById(id);
    }

    @Override
        public void deleteAiCourseListByIds(List<Long> ids) {
        // 校验存在
        validateAiCourseExists(ids);
        // 删除
        aiCourseMapper.deleteByIds(ids);
        }

    private void validateAiCourseExists(List<Long> ids) {
        List<AiCourseDO> list = aiCourseMapper.selectByIds(ids);
        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
            throw exception(BLOCKLY_NOT_EXISTS);
        }
    }

    private AiCourseDO validateAiCourseExists(Long id) {
        AiCourseDO blocklyDO = aiCourseMapper.selectById(id);
        if (blocklyDO == null) {
            throw exception(BLOCKLY_NOT_EXISTS);
        }
        return blocklyDO;
    }

    @Override
    public AiCourseDO getAiCourse(Long id) {
        return aiCourseMapper.selectById(id);
    }

    @Override
    public PageResult<AiCourseRespVO> getAiCoursePage(AiCoursePageReqVO pageReqVO) {
        pageReqVO.setPageNo((pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize());
        List<AiCoursePageReqVO> blocklyPageReqVOS = aiCourseMapper.selectAiCoursePage(pageReqVO);

        // 获取总记录数
        int total = aiCourseMapper.selectAiCoursePageCount(pageReqVO);
        // 调用服务层方法获取分页结果
        return new PageResult<>(
                blocklyPageReqVOS.stream()
                        .map(doItem -> BeanUtils.toBean(doItem, AiCourseRespVO.class))
                        .collect(Collectors.toList()),
                (long) total
        );
    }

    @Override
    public List<AiCoursePageReqVO> getAiCourseList(AiCoursePageReqVO pageReqVO) {
        return aiCourseMapper.selectAiCourseList(pageReqVO);
    }

    /**
     * 获得自身的代理对象，解决 AOP 生效问题
     *
     * @return 自己
     */
    private AiCourseServiceImpl getSelf() {
        return SpringUtil.getBean(getClass());
    }

}