package com.iformall.controller;


import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.iformall.common.ResultData;
import com.iformall.config.AwsProperty;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.*;

@RestController
@RequestMapping(value = "/api/upload")
@Api(description = "文件上传接口")
public class UploadController extends BaseController {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private AwsProperty awsProperty;

    private AmazonS3 s3 = null;

    private ResultData awsUpload(MultipartFile multiReq, ObjectMetadata metadata, String fileName) {
        ResultData data = new ResultData();
        try {
            if (s3 == null) {
                s3 = AmazonS3ClientBuilder.standard()
                        .withRegion(awsProperty.getClientRegion())
                        .withCredentials(new AWSCredentialsProvider() {
                            @Override
                            public AWSCredentials getCredentials() {
                                return new BasicAWSCredentials(awsProperty.getAccess(), awsProperty.getSecret());
                            }

                            @Override
                            public void refresh() {

                            }
                        })
                        .build();
            }

            s3.putObject(
                    new PutObjectRequest(awsProperty.getBucketName(), fileName, multiReq.getInputStream(), metadata)
                            .withCannedAcl(CannedAccessControlList.PublicRead));
            URL url = s3.getUrl(awsProperty.getBucketName(), fileName);
            logger.info(url.toString());

            data.code = ResultData.SUCCESS;
            Map<String, String> map = new HashMap<>();
            map.put("url", url.toString());
            data.data = map;
        } catch (AmazonServiceException ase) {
            data.code = ResultData.ERROR;
            logger.warn("Caught an AmazonServiceException, which " +
                    "means your request made it " +
                    "to Amazon S3, but was rejected with an error response" +
                    " for some reason.");
            logger.warn(ase.getMessage());
            data.code = ResultData.ERROR;
            data.message = "上传失败";
        } catch (AmazonClientException ace) {
            data.code = ResultData.ERROR;
            logger.warn("Caught an AmazonClientException, which " +
                    "means the client encountered " +
                    "an internal error while trying to " +
                    "communicate with S3, " +
                    "such as not being able to access the network.");
            logger.warn("Error Message: " + ace.getMessage());
            data.code = ResultData.ERROR;
            data.message = "上传失败";
        } catch (IOException ioe) {
            data.code = ResultData.ERROR;
            logger.warn("Caught an IOException: " + ioe.getMessage());
            data.code = ResultData.ERROR;
            data.message = "上传失败";
        }
        return data;
    }

    /**
     * 上传文件
     *
     * @param multiReq
     * @return
     * @throws Exception
     */
    @PostMapping(value = "/awsFileUpload", consumes = "multipart/*", headers = "content-type=multipart/form-data")
    @ApiOperation("上传文件")
    public ResultData awsfileUpload(@RequestParam("file") MultipartFile multiReq) {
        logger.info("[" + getIpAddr() + "] UploadController::awsfileUpload");

        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentType(multiReq.getContentType());
        metadata.setContentLength(multiReq.getSize());

        FileOutputStream fos = null;
        BufferedInputStream fs = null;

        String fileName = UUID.randomUUID().toString();
        int dot = multiReq.getOriginalFilename().lastIndexOf('.');
        if (dot >= 0) {
            fileName = getTenantId() + "/" + fileName + multiReq.getOriginalFilename().substring(dot, multiReq.getOriginalFilename().length());
        } else {
            fileName = getTenantId() + "/" + fileName;
        }

        ResultData data = awsUpload(multiReq, metadata, fileName);
        return data;
    }

    /**
     * 多文件上传
     *
     * @param files
     * @return
     * @throws Exception
     */
    @PostMapping(value = "/awsFilesUpload", consumes = "multipart/*", headers = "content-type=multipart/form-data")
    @ApiOperation("多文件上传")
    public ResultData awsFilesUpload(@RequestParam("files") MultipartFile[] files) {
        logger.info("[" + getIpAddr() + "] UploadController::awsFilesUpload");

        if (files.length > 0) {
            ResultData data = new ResultData();
            List<Map<String, String>> dataList = new ArrayList<Map<String, String>>();
            for (MultipartFile multipartFile : files) {
                Map<String, String> map = new HashMap<>();

                ObjectMetadata metadata = new ObjectMetadata();
                metadata.setContentType(multipartFile.getContentType());
                metadata.setContentLength(multipartFile.getSize());

                FileOutputStream fos = null;
                BufferedInputStream fs = null;

                map.put("key", multipartFile.getOriginalFilename());

                String fileName = UUID.randomUUID().toString();
                int dot = multipartFile.getOriginalFilename().lastIndexOf('.');
                if (dot >= 0) {
                    fileName = getTenantId() + "/" + fileName + multipartFile.getOriginalFilename().substring(dot, multipartFile.getOriginalFilename().length());
                } else {
                    fileName = getTenantId() + "/" + fileName;
                }

                ResultData data1 = awsUpload(multipartFile, metadata, fileName);
                if (data1.code == ResultData.SUCCESS) {
                    Map _data = (Map) data1.data;
                    map.put("url", (String) _data.get("url"));
                    dataList.add(map);
                } else {
                    // 部分成功
                    data.code = ResultData.SUCCESS;
                    data.data = dataList;
                    return data;
                }
            }
            data.code = ResultData.SUCCESS;
            data.data = dataList;
            return data;

        }
        return new ResultData();
    }

}
