package cn.wisenergy.chnmuseum.party.web.controller;

import cn.hutool.core.util.ArrayUtil;
import cn.wisenergy.chnmuseum.party.common.dfs.FastDFSUtils;
import cn.wisenergy.chnmuseum.party.common.enums.FileTypeEnum;
import cn.wisenergy.chnmuseum.party.common.enums.HANDLE_STATUS_ENUM;
import cn.wisenergy.chnmuseum.party.common.enums.RESPONSE_CODE_ENUM;
import cn.wisenergy.chnmuseum.party.common.mvc.InterfaceException;
import cn.wisenergy.chnmuseum.party.common.vo.BatchUploadResVO;
import cn.wisenergy.chnmuseum.party.common.vo.ImageUploadResult;
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.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

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

    private static final String[] IMAGE_TYPE = new String[]{"JPG", "JPEG", "PNG", "BMP", "WBMP"};
    private static final String[] AUDIO_TYPE = new String[]{"MP3", "AAC", "WMA", "WAV", "FLAC", "RM", "OGG"};
    private static final String[] VIDEO_TYPE = new String[]{"MP4", "FLV"};
    private static final String[] DOC_TYPE = new String[]{"PDF", "DOC", "DOCX", "XLS", "XLSX", "PPT", "PPTX"};
    private static final String[] DATUM_TYPE = ArrayUtil.addAll(DOC_TYPE, IMAGE_TYPE, VIDEO_TYPE);

//    @RequestMapping(value = "/upload", method = RequestMethod.POST)
//    public ResponseEntity<PicUploadResult> upload(@RequestParam(value = "bc_cover", required = true) MultipartFile uploadFile, HttpServletResponse response) throws Exception {
//        // 校验文件扩展名
//        boolean isLegal = false;
//        for (String type : IMAGE_TYPE) {
//            if (StringUtils.endsWithIgnoreCase(uploadFile.getOriginalFilename(), type)) {
//                isLegal = true;
//                break;
//            }
//        }
//        byte[] bytes = uploadFile.getBytes();
//        if (ImageUtil.isPicture(uploadFile.getOriginalFilename()) && ImageUtil.isImage(bytes) && ImageUtil.isImage1(bytes)) {
//            isLegal = true;
//        } else {
//            isLegal = false;
//            throw new RuntimeException("图片文件不合法");
//        }
//
//        // 封装Result对象,并且将文件的byte数组放置到result对象中
//        PicUploadResult fileUploadResult = new PicUploadResult();
//        // 状态
//        fileUploadResult.setError(isLegal ? 0 : 1);
//        // 文件新路径
//        String filePath = FastDFSUtils.uploadPic(bytes, uploadFile.getOriginalFilename(), uploadFile.getSize());
//
//        if (log.isDebugEnabled()) {
//            log.debug("Pic file upload .[{}] to [{}] .", uploadFile.getOriginalFilename(), filePath);
//        }
//        String picUrl = IMAGE_BASE_URL + filePath;
//        fileUploadResult.setUrl(picUrl);
//        isLegal = false;
//        try {
//            BufferedImage image = ImageIO.read(new URL(picUrl));
//            if (image != null) {
//                // fileUploadResult.setWidth(image.getWidth() + "");
//                // fileUploadResult.setHeight(image.getHeight() + "");
//                isLegal = true;
//            }
//        } catch (IOException e) {
//            log.error("check image is legal error! " + e.getMessage());
//        }
//        isLegal = true;
//        fileUploadResult.setError(isLegal ? 0 : 1);
//        if (!isLegal) {
//            // 不合法,将磁盘上的文件删除
//            FastDFSUtils.deletePic(picUrl);
//        }
//        return ResponseEntity.status(HttpStatus.CREATED).body(fileUploadResult);
//    }

    @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 ResponseEntity<BatchUploadResVO> uploadFile(@RequestPart(value = "file", required = false) MultipartFile[] files) throws IOException {
        if (files.length == 0) {
            throw new InterfaceException(RESPONSE_CODE_ENUM.SERVER_ERROR.getResultCode(), "没有文件可供上传");
        }
        int successCount = 0;
        int failureCount = 0;
        List<BatchUploadResVO.HandleResult> handleList = new ArrayList<>();

        List<String> videoUrlList = new ArrayList<>();
        for (MultipartFile file : files) {
            // 当前维度表下线结果
            BatchUploadResVO.HandleResult handleResult = new BatchUploadResVO.HandleResult();
            // 原始文件名
            String originalFilename = file.getOriginalFilename();
            if (StringUtils.isBlank(originalFilename)) {
                handleResult.setFileName("");
                handleResult.setFileType(FileTypeEnum.DATUM.getName());
                handleResult.setFileUrl("");
                handleResult.setHandleResult(HANDLE_STATUS_ENUM.FAILURE.getName());
                handleResult.setDescription("文件名为空");
                failureCount++;
                continue;
            }

            handleResult.setFileName(originalFilename);
            handleResult.setFileType(FileTypeEnum.DATUM.getName());
            handleResult.setHandleResult(HANDLE_STATUS_ENUM.SUCCESS.getName());
            boolean anyMatch = Arrays.stream(DATUM_TYPE).anyMatch(s -> Objects.equals(s, FilenameUtils.getExtension(originalFilename).toUpperCase()));
            if (anyMatch) {
                String url = FastDFSUtils.uploadFile(file.getInputStream(), file.getSize(), originalFilename);
                handleResult.setFileUrl(url);
                handleResult.setDescription("操作成功");
                videoUrlList.add(url);
                successCount++;
            } else {
                handleResult.setFileUrl("");
                handleResult.setDescription("文件格式不支持");
                failureCount++;
            }
            // 设置处理的业务表信息
            handleList.add(handleResult);
        }

        BatchUploadResVO batchUploadResVO = new BatchUploadResVO();
        batchUploadResVO.setFailureCount(failureCount);
        batchUploadResVO.setSuccessCount(successCount);
        batchUploadResVO.setTotal(files.length);
        batchUploadResVO.setHandleList(handleList);
        batchUploadResVO.setUrlList(videoUrlList);
        return ResponseEntity.ok(batchUploadResVO);
    }

    @PostMapping(value = "/image/upload", headers = "content-type=multipart/form-data", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @RequiresPermissions("image:upload")
    @ApiOperation(value = "单图片上传", notes = "单图片上传")
    public ResponseEntity<ImageUploadResult> uploadImage(@RequestParam(value = "file") MultipartFile uploadFile) throws Exception {
        if (uploadFile == null || uploadFile.getSize() == 0) {
            throw new InterfaceException(RESPONSE_CODE_ENUM.SERVER_ERROR.getResultCode(), "没有文件可供上传");
        }
        String fileName = uploadFile.getOriginalFilename();
        String extension = FilenameUtils.getExtension(fileName);
        if (StringUtils.isBlank(extension)) {
            throw new InterfaceException(RESPONSE_CODE_ENUM.SERVER_ERROR.getResultCode(), "文件格式不支持");
        }
        boolean anyMatch = Arrays.stream(IMAGE_TYPE).anyMatch(s -> Objects.equals(s, extension.toUpperCase()));
        if (!anyMatch) {
            throw new InterfaceException(RESPONSE_CODE_ENUM.SERVER_ERROR.getResultCode(), "文件格式不支持");
        }

        String url = FastDFSUtils.uploadFile(uploadFile.getInputStream(), uploadFile.getSize(), fileName);
        ImageUploadResult imageUploadResult = new ImageUploadResult();
        imageUploadResult.setFileName(fileName);
        imageUploadResult.setFileExtName(extension);
        imageUploadResult.setFileSize(uploadFile.getSize());
        imageUploadResult.setUrl(url);
        return ResponseEntity.ok(imageUploadResult);
    }


    @PostMapping(value = "/upload/allType", headers = "content-type=multipart/form-data", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @RequiresPermissions("file:upload:allType")
    @ApiOperation(value = "单文件上传(不限格式)", notes = "单文件上传(不限格式)")
    public ResponseEntity<ImageUploadResult> uploadAllType(@RequestParam(value = "file") MultipartFile uploadFile) throws Exception {
        if (uploadFile == null || uploadFile.getSize() == 0) {
            throw new InterfaceException(RESPONSE_CODE_ENUM.SERVER_ERROR.getResultCode(), "没有文件可供上传");
        }
        String fileName = uploadFile.getOriginalFilename();
        String extension = FilenameUtils.getExtension(fileName);
        if (StringUtils.isBlank(extension)) {
            throw new InterfaceException(RESPONSE_CODE_ENUM.SERVER_ERROR.getResultCode(), "文件格式不支持");
        }
//        boolean anyMatch = Arrays.stream(IMAGE_TYPE).anyMatch(s -> Objects.equals(s, extension.toUpperCase()));
//        if (!anyMatch) {
//            throw new InterfaceException(RESPONSE_CODE_ENUM.SERVER_ERROR.getResultCode(), "文件格式不支持");
//        }

        String url = FastDFSUtils.uploadFile(uploadFile.getInputStream(), uploadFile.getSize(), fileName);
        ImageUploadResult imageUploadResult = new ImageUploadResult();
        imageUploadResult.setFileName(fileName);
        imageUploadResult.setFileExtName(extension);
        imageUploadResult.setFileSize(uploadFile.getSize());
        imageUploadResult.setUrl(url);
        return ResponseEntity.ok(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)
    @RequiresPermissions("audio:upload")
    @ApiOperation(value = "多音频上传", notes = "多音频上传")
    public ResponseEntity<BatchUploadResVO> uploadAudio(@RequestPart(value = "file", required = false) MultipartFile[] files) throws IOException {
        if (files == null || files.length == 0) {
            throw new InterfaceException(RESPONSE_CODE_ENUM.SERVER_ERROR.getResultCode(), "没有文件可供上传");
        }
        final boolean existChineseAudio = Arrays.stream(files).anyMatch(s -> Objects.requireNonNull(s.getOriginalFilename()).contains("汉语"));
        if (!existChineseAudio) {
            throw new InterfaceException(RESPONSE_CODE_ENUM.SERVER_ERROR.getResultCode(), "必须包含汉语音频");
        }

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

        List<String> videoUrlList = new ArrayList<>();
        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++;
                continue;
            }

            handleResult.setFileName(originalFilename);
            handleResult.setFileType(FileTypeEnum.AUDIO.getName());
            handleResult.setHandleResult(HANDLE_STATUS_ENUM.SUCCESS.getName());
            boolean anyMatch = Arrays.stream(AUDIO_TYPE).anyMatch(s -> Objects.equals(s, FilenameUtils.getExtension(originalFilename).toUpperCase()));
            if (anyMatch) {
                String url = FastDFSUtils.uploadFile(file.getInputStream(), file.getSize(), originalFilename);
                handleResult.setFileUrl(url);
                handleResult.setDescription("操作成功");
                videoUrlList.add(url);
                successCount++;
            } else {
                handleResult.setFileUrl("");
                handleResult.setDescription("文件格式不支持");
                failureCount++;
            }
            // 设置处理的业务表信息
            handleList.add(handleResult);
        }

        BatchUploadResVO batchUploadResVO = new BatchUploadResVO();
        batchUploadResVO.setFailureCount(failureCount);
        batchUploadResVO.setSuccessCount(successCount);
        batchUploadResVO.setTotal(files.length);
        batchUploadResVO.setHandleList(handleList);
        batchUploadResVO.setUrlList(videoUrlList);
        return ResponseEntity.ok(batchUploadResVO);
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", value = "视频文件", paramType = "form", dataType = "__file", collectionFormat = "array", allowMultiple = true)
    })
    @PostMapping(value = "/video/upload", headers = "content-type=multipart/form-data", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @RequiresPermissions("video:upload")
    @ApiOperation(value = "多视频上传", notes = "多视频上传")
    public ResponseEntity<BatchUploadResVO> uploadVideo(@RequestPart(value = "file", required = true) MultipartFile[] files) throws IOException {
        if (files == null || files.length == 0) {
            throw new InterfaceException(RESPONSE_CODE_ENUM.SERVER_ERROR.getResultCode(), "没有文件可供上传");
        }
        final boolean matchChinese = Arrays.stream(files).anyMatch(s -> Objects.requireNonNull(s.getOriginalFilename()).contains("汉语"));
        if (!matchChinese) {
            throw new InterfaceException(RESPONSE_CODE_ENUM.SERVER_ERROR.getResultCode(), "必须包含汉语视频");
        }

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

        List<String> videoUrlList = new ArrayList<>();
        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++;
                continue;
            }

            handleResult.setFileName(originalFilename);
            handleResult.setFileType(FileTypeEnum.VIDEO.getName());
            handleResult.setHandleResult(HANDLE_STATUS_ENUM.SUCCESS.getName());
            boolean anyMatch = Arrays.stream(VIDEO_TYPE).anyMatch(s -> Objects.equals(s, FilenameUtils.getExtension(originalFilename).toUpperCase()));
            if (anyMatch) {
                String url = FastDFSUtils.uploadVideo(file.getInputStream(), file.getSize(), originalFilename);
                handleResult.setFileUrl(url);
                handleResult.setDescription("操作成功");
                videoUrlList.add(url);
                successCount++;
            } else {
                handleResult.setFileUrl("");
                handleResult.setDescription("文件格式不支持");
                failureCount++;
            }
            // 设置处理的业务表信息
            handleList.add(handleResult);
        }

        BatchUploadResVO batchUploadResVO = new BatchUploadResVO();
        batchUploadResVO.setFailureCount(failureCount);
        batchUploadResVO.setSuccessCount(successCount);
        batchUploadResVO.setTotal(files.length);
        batchUploadResVO.setHandleList(handleList);
        batchUploadResVO.setUrlList(videoUrlList);
        return ResponseEntity.ok(batchUploadResVO);
    }

}