package com.changfa.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.changfa.constants.ApiResult;
import com.changfa.enums.StatusEnum;
import com.changfa.entity.FileData;
import com.changfa.multi.template.MinioTemplate;
import com.changfa.service.IFileDataService;
import com.changfa.utils.MinioUtilS;
import io.minio.CreateMultipartUploadResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping(method = {RequestMethod.POST})
@Api(tags = "文件操作")
public class MinioController {

    @Autowired
    private MinioUtilS minioUtilS;
    @Autowired
    private IFileDataService fileDataService;

    @PostMapping("/upload")
    @ResponseBody
    @ApiOperation("文件上传")
    public ApiResult upload(@RequestParam("file") MultipartFile file) {
        return minioTemplate.upload(file);
    }

    @PostMapping("/removeFile/{fileId}")
    @ResponseBody
    @ApiOperation("文件删除")
    public ApiResult removeFile(@PathVariable("fileId") String fileId) {
        return minioTemplate.removeFile(fileId);
    }



    @RequestMapping(value = "/preview/{fileId}",method = {RequestMethod.POST,RequestMethod.GET})
    @ApiOperation("文件预览")
    public ResponseEntity<byte[]> preview(@PathVariable("fileId") String fileId, @ApiParam(hidden = true) HttpServletResponse response) {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.in("id", Arrays.asList(fileId));
        List<FileData> list = fileDataService.list(wrapper);
        if (!ObjectUtils.isEmpty(list)) {
            FileData fileData = list.get(0);
            try {
                return minioUtilS.download(fileData.getId(),fileData.getFileExtension(),"inline");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }


    @RequestMapping(value = "/download/{fileId}",method = {RequestMethod.POST,RequestMethod.GET})
    @ApiOperation("文件下载")
    public ResponseEntity<byte[]> download(@PathVariable("fileId") String fileId, @ApiParam(hidden = true) HttpServletResponse response) {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.in("id", Arrays.asList(fileId));
        List<FileData> list = fileDataService.list(wrapper);
        if (!ObjectUtils.isEmpty(list)) {
            FileData fileData = list.get(0);
            try {
                return minioUtilS.download(fileData.getId(),fileData.getFileExtension(),"attachment");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }


    @RequestMapping("/queryFileById/{fileId}")
    @ApiOperation("查询文件通过id")
    public ApiResult queryFileById(@PathVariable("fileId") String fileId) {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.in("id", Arrays.asList(fileId));
        List<FileData> list = fileDataService.list(wrapper);
        return ApiResult.success(list);
    }

    @RequestMapping("/queryFileByIds")
    @ApiOperation("查询文件通过多id")
    public ApiResult queryFileByIds(@RequestParam("fileIds") String fileIds) {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.in("id", Arrays.asList(fileIds.split(",")));
        List<FileData> list = fileDataService.list(wrapper);
        if (!ObjectUtils.isEmpty(list)) {
            Map<String, List<FileData>> map = list.stream().collect(Collectors.groupingBy(FileData::getId));
            return ApiResult.success(map);
        }
        return ApiResult.success(list);
    }


    @Autowired
    private MinioTemplate minioTemplate;


    /**
     * 返回分片上传需要的签名数据URL及 uploadId
     *
     * @return
     */
    @GetMapping("/createMultipartUpload")
    @SneakyThrows
    @ResponseBody
    @ApiOperation("创建分片信息")
    public ApiResult createMultipartUpload(Integer chunkSize,String fileExe) {
        // 1. 根据文件名创建签名
        String objectName = UUID.randomUUID().toString().replace("-", "");

        Map<String, Object> result = new HashMap<>();
        // 2. 获取uploadId
        CreateMultipartUploadResponse response = minioTemplate.uploadId(objectName+fileExe, null);
        String uploadId = response.result().uploadId();
        result.put("uploadId", uploadId);
        // 3. 请求Minio 服务，获取每个分块带签名的上传URL
        Map<String, String> reqParams = new HashMap<>();
        reqParams.put("uploadId", uploadId);
        result.put("fileId",objectName);
        List<String> partList = new ArrayList<>();
        // 4. 循环分块数 从1开始
        for (int i = 1; i <= chunkSize; i++) {
            reqParams.put("partNumber", String.valueOf(i));
            // 获取URL
            String uploadUrl = minioTemplate.getPresignedObjectUrl(objectName+fileExe, reqParams);
            // 添加到集合
            result.put("chunk_" + (i - 1), uploadUrl);
        }
        return ApiResult.success(result);
    }


    /**
     * 分片上传完后合并
     *
     * @param objectName 文件全路径名称
     * @param uploadId   返回的uploadId
     * @return /
     */
    @GetMapping("/completeMultipartUpload")
    @SneakyThrows
    @ResponseBody
    @ApiOperation("合并文件")
    public ApiResult completeMultipartUpload(@RequestParam String objectName,
                                             @RequestParam String uploadId,
                                             @RequestParam long fileSize,
                                             @RequestParam String fileExe,
                                             @RequestParam String originalFilename) {
        try {
           return ApiResult.success( minioTemplate.completeMultipartUpload(objectName,uploadId,fileSize,fileExe,originalFilename));
        } catch (Exception e) {
            e.printStackTrace();
            return ApiResult.error(StatusEnum.FAIL);
        }
    }


}

