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.HashMap;
import java.util.Map;
import java.util.UUID;

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

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

    @Autowired
    private AwsProperty awsProperty;

    private AmazonS3 s3 = null;

    /*
    @Value("${fileUpload.path}")
    private String filePath;

    @Value("${fileUpload.server}")
    private String server;

    @PostMapping(value = "/fileUpload", consumes = "multipart/*", headers = "content-type=multipart/form-data")
    @ApiOperation("上传文件")
    public ResultData fileUpload(@RequestParam("file") MultipartFile multiReq) {
        ResultData data = new ResultData();
        FileOutputStream fos = null;
        BufferedInputStream fs = null;
        try {
            File targetFile = new File(filePath);
            if (!targetFile.exists()) {
                targetFile.mkdirs();
            }
            String fileName = UUID.randomUUID().toString();
            int dot = multiReq.getOriginalFilename().lastIndexOf('.');
            fileName = fileName + multiReq.getOriginalFilename().substring(dot, multiReq.getOriginalFilename().length());
            fos = new FileOutputStream(new File(filePath + File.separator + fileName));
            fs = (BufferedInputStream) multiReq.getInputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = fs.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
            }
            fos.close();
            fs.close();
            data.code = ResultData.SUCCESS;
            Map<String, String> map = new HashMap<>();
            map.put("url", server + "/" + fileName);
            data.data = map;
        } catch (Exception e) {
            e.printStackTrace();
            data.code = ResultData.ERROR;
            data.message = "上传失败";
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fs != null) {
                try {
                    fs.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }


        }
        return data;
    }
    */

    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;
    }

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

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

        String fileName = multiReq.getOriginalFilename();
        fileName = "cimg/" + fileName;
        ResultData data = awsUpload(multiReq, metadata, fileName);
        return data;
    }

}
