package com.nantian.cloud.jljc.controller;

import com.nantian.sc.cloud.common.core.util.R;
import com.nantian.sc.cloud.common.minio.MinioProperties;
import com.nantian.sc.cloud.common.minio.service.MinioTemplate;
import com.nantian.sc.cloud.common.security.annotation.Inner;
import io.minio.MinioClient;
import io.minio.errors.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
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 org.xmlpull.v1.XmlPullParserException;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.HashMap;
import java.util.UUID;

@Slf4j
@CrossOrigin
@RestController
@AllArgsConstructor
@RequestMapping("/testFile")
@Api(value = "testFile", tags = "测试文件接口")
/*@Configuration
@ConfigurationProperties(prefix = "minio")*/
public class TestFileController {
    @Autowired
    private MinioTemplate minioTemplate;
    @Autowired
    private MinioProperties properties;


    @SneakyThrows
    @PostMapping("upload")
    public R upload(@RequestParam("file") MultipartFile file) {

        InputStream is = file.getInputStream(); //得到文件流
        String fileName = file.getOriginalFilename(); //文件名
        String contentType = file.getContentType();  //类型
        minioTemplate.putObject("jljc", fileName, is);
        return R.ok();
    }

    @SneakyThrows
    @PostMapping("uploadBase64")
    public R uploadBase64(@RequestParam("uuid") String uuid, @RequestParam("base64") String base64) {
        if (uuid == null || uuid == "") {
            uuid = UUID.randomUUID().toString();
        }
        ByteArrayInputStream inputStream = new ByteArrayInputStream(base64.getBytes());
        minioTemplate.putObject("jljc", uuid, inputStream);
        return R.ok(uuid);
    }

    @SneakyThrows
    @PostMapping("upload2")
    public R upload2(@RequestParam("uuid") String uuid, @RequestParam("file") MultipartFile file) {
        if (uuid == null || uuid == "") {
            uuid = UUID.randomUUID().toString();
        }
        InputStream is = file.getInputStream(); //得到文件流
        minioTemplate.putObject("jljc", uuid, is);
        return R.ok(uuid);
    }

    @SneakyThrows
    @GetMapping("downloadBase64")
    @Inner(value = false)
    public String downloadBase64(@RequestParam("uuid") String uuid) {
        InputStream fileInputStream = minioTemplate.getObject("jljc", uuid);
        byte[] data = null;
        try {
            ByteArrayOutputStream bs = new ByteArrayOutputStream();
            byte[] buff = new byte[100];
            int rc = 0;
            while ((rc = fileInputStream.read(buff, 0, 100)) > 0) {
                bs.write(buff, 0, rc);
            }
            data = bs.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return Base64.getEncoder().encodeToString(data);
    }

    @SneakyThrows
    @GetMapping("download")
    public void download(String objName, HttpServletResponse response) {
        InputStream fileInputStream = minioTemplate.getObject("jljc", objName);
        response.setHeader("Content-Disposition", "attachment;filename=" + objName);
        response.setContentType("application/force-download");
        response.setCharacterEncoding("UTF-8");
        //IOUtils.copy(fileInputStream,response.getOutputStream());
        ServletOutputStream sos = response.getOutputStream();
        byte[] buff = new byte[1024 * 8];
        int len = 0;
        while ((len = fileInputStream.read(buff)) != -1) {
            sos.write(buff, 0, buff.length);
        }
    }

    /**
     * 根据uuidStr下载文件
     */
    @Inner(value = false)
    @SneakyThrows
    @GetMapping("download2")
    @ApiOperation(value = "根据uuidStr下载文件", notes = "根据uuidStr下载文件（uuidStr为文件名、uuid的拼接）")
    @ApiImplicitParam(name = "uuidStr", value = "文件名和uuid字符串", required = true, dataType = "string", paramType = "path")
    public R download2(@RequestParam String uuidStr, HttpServletResponse response) {
        if (uuidStr == null || "".equals(uuidStr)) {
            return R.ok("文件下载失败，uuidStr不能为空！");
        }

        //uuidStr   文件名<uuid
        String[] split = uuidStr.split("<");
        String uuid = split.length == 2 ? split[1] : split[0]; //uuid
        if ("".equals(uuid)) {
            return R.ok("文件下载失败，参数不是整个uuidStr！");
        }

        //InputStream fileInputStream = minioTemplate.getObject("jljc", split[1]);
        MinioClient minioClient = new MinioClient(properties.getUrl(), properties.getAccessKey(), properties.getSecretKey());
        InputStream object = minioClient.getObject("jljc", uuid);
        byte buf[] = new byte[1024];
        int length = 0;
        response.reset();

        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(split[0], "UTF-8"));
        response.setContentType("application/octet-stream");
        response.setCharacterEncoding("utf-8");
        OutputStream outputStream = response.getOutputStream();
        while ((length = object.read(buf)) > 0) {
            outputStream.write(buf, 0, length);
        }
        outputStream.close();
        return R.ok();

    }

    //获取minio文件的下载地址
    @GetMapping("url")
    public R getUrl(String objName) {
        String url = minioTemplate.getObjectURL("jljc", objName, 10000000);
        HashMap<String, String> d = new HashMap<String, String>();
        d.put("url", url);
        return R.ok(d);
    }

    /**
     * 在线预览文件
     */
    @SneakyThrows
    @Inner(value = false)
    @GetMapping("onlinePreview")
    @ApiOperation(value = "根据uuidStr在线预览文件", notes = "根据uuidStr在线预览文件（uuidStr为文件名、uuid的拼接）")
    public R onlinePreview(String uuidStr, HttpServletResponse response) throws IOException, InvalidPortException, InvalidEndpointException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidExpiresRangeException, InternalException, NoResponseException, InvalidBucketNameException, XmlPullParserException, ErrorResponseException {
        if (uuidStr == null || "".equals(uuidStr)) {
            return R.ok("文件预览失败，uuidStr不能为空！");
        }

        //uuidStr   文件名<uuid
        String[] split = uuidStr.split("<");
        String uuid = split.length == 2 ? split[1] : split[0]; //uuid
        if ("".equals(uuid)) {
            return R.ok("文件预览失败，参数不是整个uuidStr！");
        }

        String fileName = split[0]; //文件名
        String[] strings = fileName.split("\\.");
        String fileSuffix = strings[strings.length - 1];  //文件后缀
        System.err.println("文件名称：" + fileName + "，文件后缀：" + fileSuffix + "，文件名称：" + strings[0]);

        //InputStream fileInputStream = minioTemplate.getObject("jljc", uuid);
        MinioClient minioClient = new MinioClient(properties.getUrl(), properties.getAccessKey(), properties.getSecretKey());
        InputStream fileInputStream = minioClient.getObject("jljc", uuid);

        if ("png".equals(fileSuffix) || "jpg".equals(fileSuffix) || "gif".equals(fileSuffix) || "jpeg".equals(fileSuffix)) {
            // 读取图片字节数组
            /*System.err.println("文件大小（字节）=" + fileInputStream.available());
            byte[] data = new byte[fileInputStream.available()];

            fileInputStream.read(data);
            fileInputStream.close();
            String base64Str = Base64.getEncoder().encodeToString(data);
            System.err.println("图片的base64编码：" + "data:image/png;base64," + base64Str);
            return  R.ok("data:image/png;base64," + base64Str);*/
            response.setContentType("image/jpeg;charset=utf-8");
            OutputStream sos = response.getOutputStream();
            byte[] buf = new byte[1024];
            int len;
            while ((len = fileInputStream.read(buf)) > 0) {
                sos.write(buf, 0, len);
            }
            response.flushBuffer();
            fileInputStream.close();
            sos.close();
            return R.ok();
        } else if ("xls".equals(fileSuffix) || "xlsx".equals(fileSuffix)) {
            return R.ok("excel文件");
        } else if ("doc".equals(fileSuffix) || "docx".equals(fileSuffix)) {
            return R.ok("word文件");
        } else if ("pdf".equals(fileSuffix)) {
            response.setContentType("application/pdf;charset=utf-8");
            OutputStream sos = response.getOutputStream();
            byte[] buf = new byte[1024];
            int len;
            while ((len = fileInputStream.read(buf)) > 0) {
                sos.write(buf, 0, len);
            }
            response.flushBuffer();
            fileInputStream.close();
            return R.ok();
        } else {
            return R.ok("该文件需下载查看！");
        }
    }
}
