package com.mcwl.web.controller.resource;

import com.mcwl.common.core.domain.AjaxResult;
import com.mcwl.common.core.domain.R;
import com.mcwl.common.utils.obs.ObsUtils;
import com.mcwl.resource.service.impl.FileServiceImpl;
import com.mcwl.web.controller.common.OssUtil;
import com.obs.services.ObsClient;
import com.obs.services.model.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 文件/图片
 *
 * @author DaiZibo
 * @date 2025/2/10
 * @apiNote
 */

@Slf4j
@Api(tags = "上传文件")
@RestController
@RequestMapping("/file")
public class FileController {

    @Autowired
    private FileServiceImpl fileService;

    @Autowired
    private ObsUtils obsUtils;

    @Autowired
    private ObsClient obsClient;

    /***
     *
     * 图片
     * @param file
     * @return
     */
    @ApiOperation("上传图片")
    @PostMapping("/imgUpload")
    public AjaxResult imgUpload(@RequestParam MultipartFile file) {

        String s = OssUtil.uploadMultipartFile(file);
        String fileName = file.getOriginalFilename();
        Map<String, String> map = new HashMap<>();
        map.put("fileName", fileName);
        map.put("url", s);
        return AjaxResult.success(map);
    }


    /***
     *
     * 上传文件
     * @param file
     * @return
     */
    @ApiOperation("上传文件")
    @PostMapping("/fileUpload")
    public AjaxResult fileUpload(@RequestParam MultipartFile file) {

        log.info("开始上传文件...");
        Map<String, String> map = obsUtils.uploadFile(file);

        return AjaxResult.success(map);
    }


    /***
     *
     * zip
     * @param file
     * @return
     */
    @ApiOperation(value = "zip")
    @PostMapping("/zipUrlFile")
    public AjaxResult zipUrlFile(@RequestParam MultipartFile file) {
        String s = OssUtil.uploadMultipartFile(file);
        return AjaxResult.success(s);
    }


    /***
     *
     * 下载zip
     * @param file
     * @return
     */
    @ApiOperation(value = "zip")
    @PostMapping("/zipUrl")
    public AjaxResult zipUrl(@RequestParam MultipartFile file) {
        String s = OssUtil.uploadMultipartFile(file);
        return AjaxResult.success(s);
    }


    /**
     * 根据文件名查找是否存在
     * @param name
     * @param type
     * @return
     */
    @GetMapping("/selectFileName")
    @ApiOperation(value = "根据文件名查找是否存在并返回秘钥")
    public AjaxResult selectFileName(@RequestParam String name,String type){

        return fileService.selectFileName(name,type);
    }

    @GetMapping("/selectFile")
    @ApiOperation(value = "根据文件名查找是否存在")
    public AjaxResult selectFile(@RequestParam String name,String type){

        return fileService.selectFile(name,type);
    }

    @GetMapping("/download")
    @ApiOperation(value = "读取文件内容")
    public AjaxResult download(@RequestParam String name) throws IOException {

        obsUtils.download(name);

        return AjaxResult.success();
    }



    /**
     * 启动上传任务
     */
    @GetMapping("/getUploadId/{objectKey}")
    public String getUploadId(@PathVariable("objectKey")String objectKey) {
        InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest("<桶名称>", objectKey);
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.addUserMetadata("property", "property-value");
        metadata.setContentType("text/plain");
        request.setMetadata(metadata);
        InitiateMultipartUploadResult result = obsClient.initiateMultipartUpload(request);
        String uploadId = result.getUploadId();
        return uploadId;
    }

    /**
     * 分片上传
     */
    @PostMapping("/chunk")
    public Map<String,String>  splitFileUpload(
            @RequestParam("objectKey")String objectKey,
            @RequestParam("file") MultipartFile file,
            @RequestParam("chunk") int chunk,
            @RequestParam("uploadId") String uploadId) throws Exception {
        File file1 =  multipartFileToFile(file);
        Map<String,String> map = uploadChunk(uploadId, file1, chunk, objectKey);
        return map;
    }

    /**
     * 合并上传
     */
    @PostMapping("/completeUpload")
    public CompleteMultipartUploadResult completeUpload(
            @RequestParam("objectKey")String objectKey,
            @RequestParam("uploadId") String uploadId,
            @RequestBody List<Map<String,String>> mapList
    ) {
        List<PartEtag> partEtags = new ArrayList<>();
        for(Map<String,String> map: mapList ){
            PartEtag part1 = new PartEtag();
            part1.setPartNumber(Integer.valueOf(map.get("partNumber")));
            part1.seteTag(map.get("etag"));
            partEtags.add(part1);
        }
        CompleteMultipartUploadRequest request = new CompleteMultipartUploadRequest(
                "<桶名称>", objectKey, uploadId, partEtags);
        CompleteMultipartUploadResult result = obsClient.completeMultipartUpload(request);
        return result;
    }

    /**
     * 取消任务上传
     */
    @GetMapping("/cancelUpload")
    public void cancelUpload(
            @RequestParam("objectKey")String objectKey,
            @RequestParam("uploadId") String uploadId
    ){
        AbortMultipartUploadRequest request = new AbortMultipartUploadRequest("<桶名称>", objectKey, uploadId);
        obsClient.abortMultipartUpload(request);
    }

    public Map<String,String> uploadChunk(String uploadId, File file,int chunk, String objectKey){
        // Endpoint以北京四为例，其他地区请按实际情况填写。
        Map<String,String> map = new HashMap<>();
        UploadPartRequest request = new UploadPartRequest("<桶名称>", objectKey);
        request.setUploadId(uploadId);
        request.setPartNumber(chunk);
        request.setFile(file);
        request.setPartSize(5 * 1024 * 1024L);
        UploadPartResult result = obsClient.uploadPart(request);
        map.put("etag",result.getEtag());
        map.put("partNumber",String.valueOf(result.getPartNumber()));
        return map;
    }

    /**
     * MultipartFile 转 File
     *
     * @param file
     * @throws Exception
     */
    public static File multipartFileToFile(MultipartFile file) throws Exception {

        File toFile = null;
        if (file.equals("") || file.getSize() <= 0) {
            file = null;
        } else {
            InputStream ins = null;
            ins = file.getInputStream();
            toFile = new File(file.getOriginalFilename());
            inputStreamToFile(ins, toFile);
            ins.close();
        }
        return toFile;
    }

    //获取流文件
    private static void inputStreamToFile(InputStream ins, File file) {
        try {
            OutputStream os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            ins.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 校验文件内容时候重复
     * @return
     */
    @ApiOperation(value = "校验文件hash是否重复")
    @GetMapping("/selectHash")
    public R selectHash(String hashCode,Integer type){

        return fileService.selectHash(hashCode,type);
    }

}
