package com.fjhx.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.base.BaseEntity;
import com.fjhx.entity.FileInfo;
import com.fjhx.mapper.FileInfoMapper;
import com.fjhx.service.FileInfoService;
import com.fjhx.utils.Assert;
import org.springblade.core.launch.BladeApplication;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.tool.utils.DateUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import ws.schild.jave.MultimediaInfo;
import ws.schild.jave.MultimediaObject;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 文件 服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2022-07-07
 */
@Service
public class FileInfoServiceImpl extends ServiceImpl<FileInfoMapper, FileInfo> implements FileInfoService {

    @Override
    public FileInfo uploadFile(MultipartFile file) {

        String fileName = file.getOriginalFilename();
        String suffix = FileUtil.getSuffix(fileName);

        String rootPath = BladeApplication.isLocalDev() ? "D:/hx/" : "/mnt/file/";
        String path = DateUtil.format(new Date(), "yyyy-MM/dd/");
        String filePath = path + UUID.randomUUID() + "." + suffix;

        FileUtil.mkdir(rootPath + path);

        FileOutputStream fileOutputStream = null;
        InputStream inputStream = null;

        try {
            inputStream = file.getInputStream();
            fileOutputStream = new FileOutputStream(rootPath + filePath);
            int index;
            byte[] bytes = new byte[1024];

            while ((index = inputStream.read(bytes)) != -1) {
                fileOutputStream.write(bytes, 0, index);
                fileOutputStream.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new ServiceException("上传文件失败");
        } finally {
            try {
                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        FileInfo fileInfo = new FileInfo();
        fileInfo.setFileName(fileName);
        fileInfo.setFileSuffix(suffix);

        String contentType = file.getContentType();
        fileInfo.setContentType(contentType);
        // 如果是视频，赋值视频时长
        setDuration(contentType, fileInfo, rootPath + filePath);

        fileInfo.setFileSize(file.getSize() / 1024);
        fileInfo.setFilePath(filePath);
        save(fileInfo);

        return fileInfo;
    }

    @Override
    public List<FileInfo> getFileList(Map<String, String> condition) {
        String businessId = condition.get("businessId");
        Assert.notEmpty(businessId, "业务id不能为空");

        String businessType = condition.get("businessType");

        return list(Wrappers.<FileInfo>lambdaQuery()
                .eq(FileInfo::getBusinessId, businessId)
                .eq(ObjectUtil.isNotEmpty(businessType), FileInfo::getBusinessType, businessType)
        );
    }

    public void bindingFile(String applicationName, Long businessId, Integer businessType, List<FileInfo> paramList) {
        if (paramList.size() == 0) {
            return;
        }

        for (int i = 0; i < paramList.size(); i++) {
            FileInfo fileInfo = paramList.get(i);
            fileInfo.setBusinessId(businessId);
            fileInfo.setBusinessType(businessType);
            fileInfo.setApplicationName(applicationName);
            fileInfo.setSort(i);
        }


        updateBatchById(paramList);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void againBindingFile(String applicationName, Long businessId, Integer businessType, List<FileInfo> paramList) {

        if (paramList.size() == 0) {
            return;
        }

        bindingFile(applicationName, businessId, businessType, paramList);

        List<Long> id = paramList.stream().map(FileInfo::getId).collect(Collectors.toList());

        // 删除其他文件
        remove(Wrappers.<FileInfo>lambdaQuery()
                .eq(FileInfo::getBusinessId, businessId)
                .eq(FileInfo::getBusinessType, businessType)
                .notIn(BaseEntity::getId, id));
    }

    @Override
    public void relieveBindingFile(Long businessId) {
        if (ObjectUtil.isNotEmpty(businessId)) {
            remove(FileInfo::getBusinessId, businessId);
        }
    }

    @Override
    public List<FileInfo> getFileInfo(List<Long> businessIdList) {
        return lambdaQuery().in(FileInfo::getBusinessId, businessIdList).orderByAsc(FileInfo::getSort).list();
    }

    /**
     * 如果是视频，赋值视频时长
     */
    private void setDuration(String contentType, FileInfo fileInfo, String path) {
        try {
            if (!contentType.startsWith("video")) {
                return;
            }

            File file = new File(path);
            MultimediaObject instance = new MultimediaObject(file);
            MultimediaInfo result = instance.getInfo();
            long s = result.getDuration() / 1000;
            fileInfo.setDuration(s);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("获取视频时长失败");
        }
    }

}
