package cn.chnmuseum.party.web.controller;

import cn.chnmuseum.party.common.dfs.FastDFSUtils;
import cn.chnmuseum.party.common.enums.FileCatEnum;
import cn.chnmuseum.party.common.enums.FileTypeEnum;
import cn.chnmuseum.party.common.enums.HANDLE_STATUS_ENUM;
import cn.chnmuseum.party.common.enums.LanguageEnum;
import cn.chnmuseum.party.common.util.LCSUtil;
import cn.chnmuseum.party.common.util.TimeUtils;
import cn.chnmuseum.party.common.video.VideoEncryptUtil;
import cn.chnmuseum.party.common.vo.BatchUploadResVO;
import cn.chnmuseum.party.common.vo.ImageUploadResult;
import cn.chnmuseum.party.model.Asset;
import cn.chnmuseum.party.service.AssetService;
import cn.chnmuseum.party.web.controller.base.BaseController;
import cn.hutool.core.util.ArrayUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.tobato.fastdfs.domain.fdfs.FileInfo;
import com.github.tobato.fastdfs.domain.fdfs.MetaData;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.springframework.context.annotation.Scope;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 文件上传 前端控制器
 * </p>
 *
 * @author Danny Lee
 * @since 2021-03-16
 */
@Slf4j
@RestController
@RequestMapping("/file")
@Api(tags = {"文件上传接口"})
@Scope("prototype")
public class FileUploadController extends BaseController {

    private static final String[] IMAGE_TYPE = new String[]{"JPG", "JPEG", "PNG", "BMP", "WBMP"};
    private static final String[] AUDIO_TYPE = new String[]{"MP3", "AAC", "WMA", "FLAC", "RM", "OGG"};
//    private static final String[] VIDEO_TYPE = new String[]{"MP4", "FLV", "MPEG", "MPG", "MOV"};
    //按照王亭亭提的BUG要求 修改视频界面的提示信息改为只支持MP4、flv、mov
    private static final String[] VIDEO_TYPE = new String[]{"MP4", "FLV","OGG","WEBM", "MOV"};
    private static final String[] DOC_TYPE = new String[]{"PDF", "DOC", "DOCX", "PPT", "PPTX"};
    private static final char[] SPLITTER_CHAR_2 = new char[]{'@', '#'};
    private static final char[] SPLITTER_CHAR_3 = new char[]{'@', '#', '$'};
    private static final char[] SPLITTER_CHAR_4 = new char[]{'@', '#', '$', '%'};
    private static final char[] SPLITTER_CHAR_5 = new char[]{'@', '#', '$', '%', '&'};
    private static final String[] DATUM_TYPE = ArrayUtil.addAll(DOC_TYPE, IMAGE_TYPE, VIDEO_TYPE);

    @Resource
    private AssetService assetService;

    @ApiOperation(value = "根据文件ID刪除文件", notes = "根据文件ID刪除文件")
    @DeleteMapping(value = "/delete/{id}")
    @RequiresAuthentication  //@RequiresPermissions("file:delete")
    public Map<String, Object> delete(@PathVariable(value = "id") String id) {
        final Asset asset = assetService.getById(id);
        if (asset != null) {
            final String fileUrl = asset.getFileUrl();
            final String fileUrlCrypto = asset.getFileUrlCrypto();
            try {
                FastDFSUtils.deleteFile(fileUrl);
                FastDFSUtils.deleteFile(fileUrlCrypto);
            } catch (Throwable e) {
                this.assetService.removeById(id);
                return getResult("文件已被删除");
            }
            this.assetService.removeById(id);
            return getSuccessResult();
        }
        return getResult("文件已被删除");
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", value = "资料", paramType = "form", dataType = "__file", collectionFormat = "array", allowMultiple = true)
    })
    @PostMapping(value = "/datum/upload", headers = "content-type=multipart/form-data", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @ApiOperation(value = "展板资料上传", notes = "展板资料上传")
    public Map<String, Object> uploadDatum(@RequestPart(value = "file", required = false) MultipartFile[] files) throws IOException {
        if (files == null || files.length == 0) {
            return getFailResult("没有文件可供上传");
        }
        int successCount = 0;
        int failureCount = 0;
        List<BatchUploadResVO.HandleResult> handleList = new ArrayList<>();

        Set<Asset> datumUrlList = new LinkedHashSet<>();
        for (MultipartFile file : files) {
            // 当前维度表下线结果
            BatchUploadResVO.HandleResult handleResult = new BatchUploadResVO.HandleResult();
            // 原始文件名
            String originalFilename = file.getOriginalFilename();
            if (StringUtils.isBlank(originalFilename)) {
                handleResult.setFileName("");
                handleResult.setFileUrl("");
                handleResult.setHandleResult(HANDLE_STATUS_ENUM.FAILURE.getName());
                handleResult.setDescription("文件名为空");
                failureCount++;
                handleList.add(handleResult);
                continue;
            }
            if (file.getSize() == 0L) {
                handleResult.setFileName("");
                handleResult.setFileUrl("");
                handleResult.setHandleResult(HANDLE_STATUS_ENUM.FAILURE.getName());
                handleResult.setDescription("文件" + originalFilename + "大小为0");
                failureCount++;
                handleList.add(handleResult);
                continue;
            }

            String baseName = FilenameUtils.getBaseName(originalFilename);
            String extName = FilenameUtils.getExtension(originalFilename);
            String finalExtName = extName;
            boolean anyMatch = Arrays.stream(DATUM_TYPE).anyMatch(s -> Objects.equals(s, finalExtName.toUpperCase()));
            if (anyMatch) {
                if ("MPEG".equals(extName.toUpperCase()) || "MOV".equals(extName.toUpperCase())) {
                    extName = "mp4";
                    originalFilename = FilenameUtils.getBaseName(originalFilename) + "." + extName;
                }
                final Asset asset = Asset.builder()
                        .fileName(originalFilename)
                        .fileExtName(extName)
                        .fileCat(FileCatEnum.EXHIBITION_BOARD_DATUM.name())
                        .build();

                String language = null;
                final Set<MetaData> metaDataSet = new HashSet<>();
                metaDataSet.add(new MetaData("fileName", originalFilename));
                if (originalFilename.contains("汉语")) {
                    metaDataSet.add(new MetaData("language", LanguageEnum.ZH.name()));
                    language = LanguageEnum.ZH.name();
                } else if (originalFilename.contains("英语")) {
                    metaDataSet.add(new MetaData("language", LanguageEnum.EN.name()));
                    language = LanguageEnum.EN.name();
                } else if (originalFilename.contains("蒙语")) {
                    metaDataSet.add(new MetaData("language", LanguageEnum.MN.name()));
                    language = LanguageEnum.MN.name();
                } else if (originalFilename.contains("藏语")) {
                    metaDataSet.add(new MetaData("language", LanguageEnum.BO.name()));
                    language = LanguageEnum.BO.name();
                } else if (originalFilename.contains("维吾尔语")) {
                    metaDataSet.add(new MetaData("language", LanguageEnum.UYG.name()));
                    language = LanguageEnum.UYG.name();
                }

                String fileUrl = null;
                String fileUrlCrypto = null;
                if (Arrays.stream(VIDEO_TYPE).anyMatch(s -> Objects.equals(s, finalExtName.toUpperCase()))) {
                    metaDataSet.add(new MetaData("fileType", FileTypeEnum.VIDEO.name()));
                    handleResult.setFileType(FileTypeEnum.VIDEO.name());
                    asset.setFileType(FileTypeEnum.VIDEO.name());

                    final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                    IOUtils.copy(file.getInputStream(), byteArrayOutputStream);
                    fileUrl = FastDFSUtils.uploadVideo(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()), file.getSize(), originalFilename, metaDataSet);
                    metaDataSet.removeIf(x -> "MD5".equals(x.getName()));
                    metaDataSet.add(new MetaData("fileName", baseName + ".chnmuseum"));
                    fileUrlCrypto = FastDFSUtils.uploadVideo(VideoEncryptUtil.encrypt(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()), VideoEncryptUtil.cipher), file.getSize(), baseName + ".chnmuseum", metaDataSet);
                    final Set<MetaData> fileMetaData = FastDFSUtils.getFileMetaData(fileUrlCrypto);
                    String md5 = fileMetaData.stream().filter(x -> "MD5".equals(x.getName())).map(MetaData::getValue).findFirst().get();
                    asset.setMd5(md5);
                    asset.setIntro(Base64.getEncoder().encodeToString(fileUrl.getBytes()));
                    asset.setFileNameCrypto(md5 + ".chnmuseum");
                    asset.setFileUrlCrypto(fileUrlCrypto);
                    asset.setFileUrl(fileUrl);        //mall/learningContent/get   这个接口返回的 fileUrl 是空字符安串    BUG修改
                } else if (Arrays.stream(AUDIO_TYPE).anyMatch(s -> Objects.equals(s, finalExtName.toUpperCase()))) {
                    metaDataSet.add(new MetaData("fileType", FileTypeEnum.AUDIO.name()));
                    handleResult.setFileType(FileTypeEnum.AUDIO.name());
                    asset.setFileType(FileTypeEnum.AUDIO.name());
                    fileUrl = FastDFSUtils.uploadFile(file.getInputStream(), file.getSize(), originalFilename, metaDataSet);
                    asset.setFileUrl(fileUrl);
                } else if (Arrays.stream(IMAGE_TYPE).anyMatch(s -> Objects.equals(s, finalExtName.toUpperCase()))) {
                    metaDataSet.add(new MetaData("fileType", FileTypeEnum.IMAGE.name()));
                    handleResult.setFileType(FileTypeEnum.IMAGE.name());
                    asset.setFileType(FileTypeEnum.IMAGE.name());
                    fileUrl = FastDFSUtils.uploadFile(file.getInputStream(), file.getSize(), originalFilename, metaDataSet);
                    asset.setThumbnail(fileUrl);
                    asset.setFileUrl(fileUrl);
                } else if (Arrays.stream(DOC_TYPE).anyMatch(s -> Objects.equals(s, finalExtName.toUpperCase()))) {
                    metaDataSet.add(new MetaData("fileType", FileTypeEnum.DOCUMENT.name()));
                    handleResult.setFileType(FileTypeEnum.DOCUMENT.name());
                    asset.setFileType(FileTypeEnum.DOCUMENT.name());
                    fileUrl = FastDFSUtils.uploadFile(file.getInputStream(), file.getSize(), originalFilename, metaDataSet);
                    asset.setFileUrl(fileUrl);
                }
                final FileInfo fileInfo = FastDFSUtils.getFileInfo(fileUrl);
                final LocalDateTime createTime = TimeUtils.getDateTimeOfTimestamp(fileInfo.getCreateTime() * 1000);
                asset.setFileSize(fileInfo.getFileSize());
                asset.setFileCat(FileCatEnum.EXHIBITION_BOARD_DATUM.name());
                asset.setLanguage(language);
                asset.setCreateTime(createTime);
                asset.setUpdateTime(createTime);
                if (Arrays.stream(VIDEO_TYPE).anyMatch(s -> Objects.equals(s, finalExtName.toUpperCase()))) {
                    final int crc32 = fileInfo.getCrc32();
                    final Asset one = this.assetService.getOne(Wrappers.<Asset>lambdaQuery().eq(Asset::getCrc32, (long) crc32).last(" limit 1"));
                    asset.setCrc32((long) crc32);
                    if (one != null) {
                        try {
                            FastDFSUtils.deleteFile(fileUrl);
                            FastDFSUtils.deleteFile(fileUrlCrypto);
                        } catch (Throwable ignored) {
                        }
                        asset.setIntro(one.getIntro());
                        asset.setFileUrlCrypto(one.getFileUrlCrypto());
                        asset.setFileNameCrypto(one.getFileNameCrypto());
                        asset.setMd5(one.getMd5());
                        asset.setCrc32(one.getCrc32());
                        asset.setFileUrl(one.getFileUrl());
                    }
                }
                this.assetService.save(asset);
                datumUrlList.add(asset);

                handleResult.setFileUrl("");
                handleResult.setFileName(originalFilename);
                handleResult.setHandleResult(HANDLE_STATUS_ENUM.SUCCESS.getName());
                handleResult.setDescription("");
                successCount++;
            } else {
                handleResult.setFileUrl("");
                handleResult.setDescription("文件" + originalFilename + "格式不支持");
                failureCount++;
            }
            // 设置处理的业务表信息
            handleList.add(handleResult);
        }
        BatchUploadResVO batchUploadResVO = new BatchUploadResVO();
        batchUploadResVO.setFailureCount(failureCount);
        batchUploadResVO.setSuccessCount(successCount);
        batchUploadResVO.setTotal(files.length);
        batchUploadResVO.setHandleList(handleList);
        batchUploadResVO.setFileList(datumUrlList);

        if (failureCount > 0) {
            return getFailResult(batchUploadResVO);
        }
        return getResult(batchUploadResVO);
    }

    @PostMapping(value = "/image/upload", headers = "content-type=multipart/form-data", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @RequiresAuthentication  //@RequiresPermissions("file:image:upload")
    @ApiOperation(value = "单图片上传(封面/缩略图)", notes = "单图片上传(封面/缩略图)")
    public Map<String, Object> uploadImage(@RequestParam(value = "file") MultipartFile uploadFile) throws Exception {
        if (uploadFile == null) {
            return getFailResult("没有文件可供上传");
        }
        String fileName = uploadFile.getOriginalFilename();
        String extension = FilenameUtils.getExtension(fileName);
        if (StringUtils.isBlank(extension)) {
            return getFailResult("文件格式不支持");
        }
        boolean anyMatch = Arrays.stream(IMAGE_TYPE).anyMatch(s -> Objects.equals(s, extension.toUpperCase()));
        if (!anyMatch) {
            return getFailResult("文件格式不支持");
        }

        final Set<MetaData> metaDataSet = new HashSet<>();
        metaDataSet.add(new MetaData("fileName", fileName));
        metaDataSet.add(new MetaData("fileType", FileTypeEnum.IMAGE.name()));
        String url = FastDFSUtils.uploadFile(uploadFile.getInputStream(), uploadFile.getSize(), fileName, metaDataSet);
        ImageUploadResult imageUploadResult = new ImageUploadResult();
        imageUploadResult.setFileName(fileName);
        imageUploadResult.setFileExtName(extension);
        imageUploadResult.setFileSize(uploadFile.getSize());
        imageUploadResult.setUrl(url);
        return getResult(imageUploadResult);
    }

    @PostMapping(value = "/upload/allType", headers = "content-type=multipart/form-data", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @RequiresAuthentication  //@RequiresPermissions("file:upload:allType")
    @ApiOperation(value = "单文件上传(不限格式)", notes = "单文件上传(不限格式)")
    public Map<String, Object> uploadAllType(@RequestParam(value = "file") MultipartFile uploadFile) throws Exception {
        if (uploadFile == null) {
            return getFailResult("没有文件可供上传");
        }
        String fileName = uploadFile.getOriginalFilename();
        String extension = FilenameUtils.getExtension(fileName);
        if (StringUtils.isBlank(extension)) {
            return getFailResult("文件格式不支持");
        }
        final Set<MetaData> metaDataSet = new HashSet<>();
        metaDataSet.add(new MetaData("fileName", fileName));
        String url = FastDFSUtils.uploadFile(uploadFile.getInputStream(), uploadFile.getSize(), fileName, metaDataSet);
        ImageUploadResult imageUploadResult = new ImageUploadResult();
        imageUploadResult.setFileName(fileName);
        imageUploadResult.setFileExtName(extension);
        imageUploadResult.setFileSize(uploadFile.getSize());
        imageUploadResult.setUrl(url);
        return getResult(imageUploadResult);
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", value = "音频文件", paramType = "form", dataType = "__file", collectionFormat = "array", allowMultiple = true)
    })
    @PostMapping(value = "/audio/upload", headers = "content-type=multipart/form-data", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @RequiresAuthentication  //@RequiresPermissions("audio:upload")
    @ApiOperation(value = "展板多音频上传", notes = "展板多音频上传")
    public Map<String, Object> uploadAudio(@RequestPart(value = "file", required = false) MultipartFile[] files) throws IOException {
        if (files == null || files.length == 0) {
            return getFailResult("没有文件可供上传");
        }
        final boolean existChineseAudio = Arrays.stream(files).anyMatch(s -> Objects.requireNonNull(s.getOriginalFilename()).contains("汉语"));
        if (!existChineseAudio) {
            return getFailResult("必须包含汉语音频");
        }

        int successCount = 0;
        int failureCount = 0;
        List<BatchUploadResVO.HandleResult> handleList = new ArrayList<>();

        Set<Asset> fileList = new LinkedHashSet<>();
        for (MultipartFile file : files) {
            // 当前维度表下线结果
            BatchUploadResVO.HandleResult handleResult = new BatchUploadResVO.HandleResult();
            // 原始文件名
            String originalFilename = file.getOriginalFilename();
            if (StringUtils.isBlank(originalFilename)) {
                handleResult.setFileName("");
                handleResult.setFileType(FileTypeEnum.AUDIO.getName());
                handleResult.setFileUrl("");
                handleResult.setHandleResult(HANDLE_STATUS_ENUM.FAILURE.getName());
                handleResult.setDescription("文件名为空");
                failureCount++;
                handleList.add(handleResult);
                continue;
            }
            if (file.getSize() == 0L) {
                handleResult.setFileName("");
                handleResult.setFileUrl("");
                handleResult.setHandleResult(HANDLE_STATUS_ENUM.FAILURE.getName());
                handleResult.setDescription("文件" + originalFilename + "大小为0");
                failureCount++;
                handleList.add(handleResult);
                continue;
            }

            String extName = FilenameUtils.getExtension(originalFilename);
            boolean anyMatch = Arrays.stream(AUDIO_TYPE).anyMatch(s -> Objects.equals(s, extName.toUpperCase()));
            if (anyMatch) {
                String language = null;
                final Set<MetaData> metaDataSet = new HashSet<>();
                metaDataSet.add(new MetaData("fileName", originalFilename));
                metaDataSet.add(new MetaData("fileType", FileTypeEnum.AUDIO.name()));
                if (originalFilename.contains("汉语")) {
                    metaDataSet.add(new MetaData("language", LanguageEnum.ZH.name()));
                    language = LanguageEnum.ZH.name();
                } else if (originalFilename.contains("英语")) {
                    metaDataSet.add(new MetaData("language", LanguageEnum.EN.name()));
                    language = LanguageEnum.EN.name();
                } else if (originalFilename.contains("蒙语")) {
                    metaDataSet.add(new MetaData("language", LanguageEnum.MN.name()));
                    language = LanguageEnum.MN.name();
                } else if (originalFilename.contains("藏语")) {
                    metaDataSet.add(new MetaData("language", LanguageEnum.BO.name()));
                    language = LanguageEnum.BO.name();
                } else if (originalFilename.contains("维吾尔语")) {
                    metaDataSet.add(new MetaData("language", LanguageEnum.UYG.name()));
                    language = LanguageEnum.UYG.name();
                }
                String fileUrl = FastDFSUtils.uploadFile(file.getInputStream(), file.getSize(), originalFilename, metaDataSet);
                final FileInfo fileInfo = FastDFSUtils.getFileInfo(fileUrl);
                final int crc32 = fileInfo.getCrc32();
                final Asset one = this.assetService.getOne(Wrappers.<Asset>lambdaQuery().eq(Asset::getCrc32, (long) crc32).last(" limit 1"));
                final LocalDateTime createTime = TimeUtils.getDateTimeOfTimestamp(fileInfo.getCreateTime() * 1000);
                final long fileSize = fileInfo.getFileSize();
                final Asset asset = Asset.builder()
                        .fileName(originalFilename)
                        .fileExtName(extName)
                        .fileType(FileTypeEnum.AUDIO.name())
                        .fileUrl(fileUrl)
                        .fileSize(fileSize)
                        .fileCat(FileCatEnum.EXHIBITION_BOARD_AUDIO.name())
                        .language(language)
                        .crc32((long) crc32)
                        .createTime(createTime)
                        .updateTime(createTime)
                        .build();
                if (one != null) {
                    FastDFSUtils.deleteFile(fileUrl);
                    asset.setFileUrl(one.getFileUrl());
                    asset.setCrc32(one.getCrc32());
                }
                this.assetService.save(asset);
                fileList.add(asset);

                handleResult.setFileUrl(fileUrl);
                handleResult.setFileName(originalFilename);
                handleResult.setFileType(FileTypeEnum.AUDIO.getName());
                handleResult.setHandleResult(HANDLE_STATUS_ENUM.SUCCESS.getName());
                handleResult.setDescription("");
                successCount++;
            } else {
                handleResult.setFileUrl("");
                handleResult.setFileType(FileTypeEnum.AUDIO.getName());
                handleResult.setHandleResult(HANDLE_STATUS_ENUM.FAILURE.getName());
                handleResult.setDescription("文件" + originalFilename + "格式不支持");
                failureCount++;
            }
            // 设置处理的业务表信息
            handleList.add(handleResult);
        }

        BatchUploadResVO batchUploadResVO = new BatchUploadResVO();
        batchUploadResVO.setFailureCount(failureCount);
        batchUploadResVO.setSuccessCount(successCount);
        batchUploadResVO.setTotal(files.length);
        batchUploadResVO.setHandleList(handleList);
        batchUploadResVO.setFileList(fileList);
        return getResult(batchUploadResVO);
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", value = "视频文件", paramType = "form", dataType = "__file", collectionFormat = "array", allowMultiple = true, required = true)
    })
    @PostMapping(value = "/video/content/upload", headers = "content-type=multipart/form-data", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @RequiresAuthentication  //@RequiresPermissions("file:video:content:upload")
    @ApiOperation(value = "展板视频上传", notes = "展板视频上传")
    public Map<String, Object> uploadContentVideo(@RequestPart("file") MultipartFile[] files) throws Exception {
        if (files == null || files.length == 0) {
            return getFailResult("没有文件可供上传");
        }
        if (files.length == 1) {
            String extName = FilenameUtils.getExtension(files[0].getOriginalFilename());
            boolean anyMatch = Arrays.stream(VIDEO_TYPE).anyMatch(s -> Objects.equals(s, extName.toUpperCase()));
            if (!anyMatch) {
//                return getFailResult("目前仅支持" + String.join("、", VIDEO_TYPE) + "格式");
                return getFailResult("支持h264编码的MP4视频、VP8编码的webm视频和Theora编码的ogg视频");
            }
        }
        String videoContentName = null;
        String text;
        LCSUtil strie = null;
        final String[] fileBaseNameArray = Arrays.stream(files).map(x -> FilenameUtils.getBaseName(x.getOriginalFilename())).toArray(String[]::new);
        switch (fileBaseNameArray.length) {
            case 1:
                videoContentName = fileBaseNameArray[0];
                break;
            case 2:
                text = fileBaseNameArray[0] + SPLITTER_CHAR_2[0] + fileBaseNameArray[1] + SPLITTER_CHAR_2[1];
                strie = new LCSUtil(text, SPLITTER_CHAR_2);
                break;
            case 3:
                text = fileBaseNameArray[0] + SPLITTER_CHAR_3[0] + fileBaseNameArray[1] + SPLITTER_CHAR_3[1] + fileBaseNameArray[2] + SPLITTER_CHAR_3[2];
                strie = new LCSUtil(text, SPLITTER_CHAR_3);
                break;
            case 4:
                text = fileBaseNameArray[0] + SPLITTER_CHAR_4[0] + fileBaseNameArray[1] + SPLITTER_CHAR_4[1] + fileBaseNameArray[2] + SPLITTER_CHAR_4[2] + fileBaseNameArray[3] + SPLITTER_CHAR_4[3];
                strie = new LCSUtil(text, SPLITTER_CHAR_4);
                break;
            case 5:
                text = fileBaseNameArray[0] + SPLITTER_CHAR_5[0] + fileBaseNameArray[1] + SPLITTER_CHAR_5[1] + fileBaseNameArray[2] + SPLITTER_CHAR_5[2] + fileBaseNameArray[3] + SPLITTER_CHAR_5[3] + fileBaseNameArray[4] + SPLITTER_CHAR_5[4];
                strie = new LCSUtil(text, SPLITTER_CHAR_5);
                break;
            default:
                break;
        }
        if (strie != null) {
            strie.buildSuffixTree();
            videoContentName = strie.findLCS();
            if (StringUtils.isBlank(videoContentName)) {
                return getFailResult("请修改你的文件名并保持前缀一致后再上传");
            } else {
                videoContentName = videoContentName.trim();
                videoContentName = StringUtils.removeEnd(videoContentName, "{");
                videoContentName = StringUtils.removeEnd(videoContentName, "[");
                videoContentName = StringUtils.removeEnd(videoContentName, "【");
                videoContentName = StringUtils.removeEnd(videoContentName, "(");
                videoContentName = StringUtils.removeEnd(videoContentName, "(");
                videoContentName = StringUtils.removeEnd(videoContentName, "-");
                videoContentName = StringUtils.removeEnd(videoContentName, "_");
                videoContentName = StringUtils.removeEnd(videoContentName, "之");
            }
        }

        int successCount = 0;
        int failureCount = 0;
        List<BatchUploadResVO.HandleResult> handleList = new ArrayList<>();

        Set<Asset> fileList = new LinkedHashSet<>();
        for (MultipartFile file : files) {
            // 当前维度表下线结果
            BatchUploadResVO.HandleResult handleResult = new BatchUploadResVO.HandleResult();
            // 原始文件名
            String originalFilename = file.getOriginalFilename();
            if (StringUtils.isBlank(originalFilename)) {
                handleResult.setFileName("");
                handleResult.setFileType(FileTypeEnum.VIDEO.getName());
                handleResult.setFileUrl("");
                handleResult.setHandleResult(HANDLE_STATUS_ENUM.FAILURE.getName());
                handleResult.setDescription("文件名为空");
                failureCount++;
                handleList.add(handleResult);
                continue;
            }
            if (file.getSize() == 0L) {
                handleResult.setFileName("");
                handleResult.setFileUrl("");
                handleResult.setHandleResult(HANDLE_STATUS_ENUM.FAILURE.getName());
                handleResult.setDescription("文件" + originalFilename + "大小为0");
                failureCount++;
                handleList.add(handleResult);
                continue;
            }

            final String baseName = FilenameUtils.getBaseName(originalFilename);
            String extName = FilenameUtils.getExtension(originalFilename);
            String finalExtName = extName;
            boolean anyMatch = Arrays.stream(VIDEO_TYPE).anyMatch(s -> Objects.equals(s, finalExtName.toUpperCase()));
            if (anyMatch) {
                if ("MPEG".equals(extName.toUpperCase()) || "MOV".equals(extName.toUpperCase())) {
                    extName = "mp4";
                    originalFilename = baseName + "." + extName;
                }
                String language = null;
                final Set<MetaData> metaDataSet = new HashSet<>();
                metaDataSet.add(new MetaData("fileName", originalFilename));
                metaDataSet.add(new MetaData("fileType", FileTypeEnum.VIDEO.name()));
                if (originalFilename.contains("汉语")) {
                    metaDataSet.add(new MetaData("language", LanguageEnum.ZH.name()));
                    language = LanguageEnum.ZH.name();
                } else if (originalFilename.contains("蒙语")) {
                    metaDataSet.add(new MetaData("language", LanguageEnum.MN.name()));
                    language = LanguageEnum.MN.name();
                } else if (originalFilename.contains("藏语")) {
                    metaDataSet.add(new MetaData("language", LanguageEnum.BO.name()));
                    language = LanguageEnum.BO.name();
                } else if (originalFilename.contains("维吾尔语")) {
                    metaDataSet.add(new MetaData("language", LanguageEnum.UYG.name()));
                    language = LanguageEnum.UYG.name();
                    //加上英语
                }else if (originalFilename.contains("英语")) {
                    metaDataSet.add(new MetaData("language", LanguageEnum.EN.name()));
                    language = LanguageEnum.EN.name();
                }
                final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                IOUtils.copy(file.getInputStream(), byteArrayOutputStream);
                final String fileUrl = FastDFSUtils.uploadVideo(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()), file.getSize(), originalFilename, metaDataSet);
                metaDataSet.removeIf(x -> "MD5".equals(x.getName()));
                metaDataSet.add(new MetaData("fileName", baseName + ".chnmuseum"));
                final String fileUrlCrypto = FastDFSUtils.uploadVideo(VideoEncryptUtil.encrypt(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()), VideoEncryptUtil.cipher), file.getSize(), baseName + ".chnmuseum", metaDataSet);
                final Set<MetaData> fileMetaData = FastDFSUtils.getFileMetaData(fileUrlCrypto);
                String md5 = fileMetaData.stream().filter(x -> "MD5".equals(x.getName())).map(MetaData::getValue).findFirst().get();

                final FileInfo fileInfo = FastDFSUtils.getFileInfo(fileUrl);
                final int crc32 = fileInfo.getCrc32();
                final Asset one = this.assetService.getOne(Wrappers.<Asset>lambdaQuery().eq(Asset::getCrc32, (long) crc32).last(" limit 1"));
                final LocalDateTime createTime = TimeUtils.getDateTimeOfTimestamp(fileInfo.getCreateTime() * 1000);
                final long fileSize = fileInfo.getFileSize();
                final Asset asset = Asset.builder()
                        .fileName(originalFilename)
                        .fileNameCrypto(md5 + ".chnmuseum")
                        .fileExtName(extName)
                        .fileType(FileTypeEnum.VIDEO.name())
                        .fileSize(fileSize)
                        .intro(Base64.getEncoder().encodeToString(fileUrl.getBytes()))
                        .fileUrlCrypto(fileUrlCrypto)
                        .fileUrl(fileUrl)
                        .fileCat(FileCatEnum.VIDEO_CONTENT.name())
                        .language(language)
                        .md5(md5)
                        .crc32((long) crc32)
                        .videoContentName(videoContentName)
                        .createTime(createTime)
                        .updateTime(createTime)
                        .build();
                if (one != null) {
                    FastDFSUtils.deleteFile(fileUrl);
                    FastDFSUtils.deleteFile(fileUrlCrypto);
                    asset.setIntro(one.getIntro());
                    asset.setFileUrlCrypto(one.getFileUrlCrypto());
                    asset.setFileUrl(one.getFileUrl());
                    asset.setFileNameCrypto(one.getFileNameCrypto());
                    asset.setMd5(one.getMd5());
                    asset.setCrc32(one.getCrc32());
                }
                this.assetService.save(asset);
                fileList.add(asset);

                handleResult.setFileUrl("");
                handleResult.setFileName(originalFilename);
                handleResult.setFileType(FileTypeEnum.VIDEO.getName());
                handleResult.setHandleResult(HANDLE_STATUS_ENUM.SUCCESS.getName());
                handleResult.setDescription("");
                successCount++;
            } else {
                handleResult.setFileUrl("");
                handleResult.setHandleResult("上传失败");
                handleResult.setDescription("文件" + originalFilename + "格式不支持");
                failureCount++;
            }
            // 设置处理的业务表信息
            handleList.add(handleResult);
        }

        BatchUploadResVO batchUploadResVO = new BatchUploadResVO();
        batchUploadResVO.setFailureCount(failureCount);
        batchUploadResVO.setSuccessCount(successCount);
        batchUploadResVO.setTotal(files.length);
        batchUploadResVO.setHandleList(handleList);
        batchUploadResVO.setFileList(fileList);
        return getResult(batchUploadResVO);
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", value = "视频文件", paramType = "form", dataType = "__file", collectionFormat = "array", allowMultiple = true, required = true)
    })
    @PostMapping(value = "/video/upload", headers = "content-type=multipart/form-data", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @RequiresAuthentication  //@RequiresPermissions("file:video:upload")
    @ApiOperation(value = "多视频上传", notes = "多视频上传")
    public Map<String, Object> uploadVideo(@RequestPart("file") MultipartFile[] files) throws IOException {
        if (files == null || files.length == 0) {
            return getFailResult("没有文件可供上传");
        }
        if (files.length == 1) {
            String extName = FilenameUtils.getExtension(files[0].getOriginalFilename());
            boolean anyMatch = Arrays.stream(VIDEO_TYPE).anyMatch(s -> Objects.equals(s, extName.toUpperCase()));
            if (!anyMatch) {
//                return getFailResult("目前仅支持" + String.join("、", VIDEO_TYPE) + "格式");
                return getFailResult("支持h264编码的MP4视频、VP8编码的webm视频和Theora编码的ogg视频");
            }
        }

        int successCount = 0;
        int failureCount = 0;
        List<BatchUploadResVO.HandleResult> handleList = new ArrayList<>();

        Set<Asset> fileList = new LinkedHashSet<>();
        for (MultipartFile file : files) {
            // 当前维度表下线结果
            BatchUploadResVO.HandleResult handleResult = new BatchUploadResVO.HandleResult();
            // 原始文件名
            String originalFilename = file.getOriginalFilename();
            if (StringUtils.isBlank(originalFilename)) {
                handleResult.setFileName("");
                handleResult.setFileType(FileTypeEnum.VIDEO.getName());
                handleResult.setFileUrl("");
                handleResult.setHandleResult(HANDLE_STATUS_ENUM.FAILURE.getName());
                handleResult.setDescription("文件名为空");
                failureCount++;
                handleList.add(handleResult);
                continue;
            }
            if (file.getSize() == 0L) {
                handleResult.setFileName("");
                handleResult.setFileUrl("");
                handleResult.setHandleResult(HANDLE_STATUS_ENUM.FAILURE.getName());
                handleResult.setDescription("文件" + originalFilename + "大小为0");
                failureCount++;
                handleList.add(handleResult);
                continue;
            }

            String extName = FilenameUtils.getExtension(originalFilename);
            String finalExtName = extName;
            boolean anyMatch = Arrays.stream(VIDEO_TYPE).anyMatch(s -> Objects.equals(s, finalExtName.toUpperCase()));
            if (anyMatch) {
                if ("MPEG".equals(extName.toUpperCase()) || "MOV".equals(extName.toUpperCase())) {
                    extName = "mp4";
                    originalFilename = FilenameUtils.getBaseName(originalFilename) + "." + extName;
                }
                final Set<MetaData> metaDataSet = new HashSet<>();
                metaDataSet.add(new MetaData("fileName", originalFilename));
                metaDataSet.add(new MetaData("fileType", FileTypeEnum.VIDEO.name()));
                final String fileUrl = FastDFSUtils.uploadFile(file.getInputStream(), file.getSize(), originalFilename, metaDataSet);
                final FileInfo fileInfo = FastDFSUtils.getFileInfo(fileUrl);
                final Asset asset = Asset.builder()
                        .fileName(originalFilename)
                        .fileExtName(extName)
                        .fileType(FileTypeEnum.VIDEO.name())
                        .fileSize(fileInfo.getFileSize())
                        .fileUrl(fileUrl)
                        .fileCat(FileCatEnum.VIEWING_INTERACTION.name())
                        .crc32((long) fileInfo.getCrc32())
                        .build();
                this.assetService.save(asset);
                fileList.add(asset);

                handleResult.setFileUrl(fileUrl);
                handleResult.setFileName(originalFilename);
                handleResult.setFileType(FileTypeEnum.VIDEO.getName());
                handleResult.setHandleResult(HANDLE_STATUS_ENUM.SUCCESS.getName());
                handleResult.setDescription("");
                successCount++;
            } else {
                handleResult.setFileUrl("");
                handleResult.setHandleResult("上传失败");
                handleResult.setDescription("文件" + originalFilename + "格式不支持");
                failureCount++;
            }
            // 设置处理的业务表信息
            handleList.add(handleResult);
        }

        BatchUploadResVO batchUploadResVO = new BatchUploadResVO();
        batchUploadResVO.setFailureCount(failureCount);
        batchUploadResVO.setSuccessCount(successCount);
        batchUploadResVO.setTotal(files.length);
        batchUploadResVO.setHandleList(handleList);
        batchUploadResVO.setFileList(fileList);
        return getResult(batchUploadResVO);
    }

}