package com.sqx.modules.file;


import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.tea.TeaException;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.region.Region;
import com.sqx.common.utils.Result;
import com.sqx.modules.common.service.CommonInfoService;
import com.sqx.modules.file.utils.FileUploadUtils;
import com.volcengine.tos.TOSV2;
import com.volcengine.tos.TOSV2ClientBuilder;
import com.volcengine.tos.TosClientException;
import com.volcengine.tos.TosServerException;
import com.volcengine.tos.model.object.PutObjectFromFileInput;
import com.volcengine.tos.model.object.PutObjectFromFileOutput;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import com.aliyun.sts20150401.models.AssumeRoleResponse;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;
import java.util.UUID;



/**
 * 阿里云文件上传
 * @author fang
 * @date 2020/7/13
 */
@RestController
@Api(value = "阿里云文件上传", tags = {"阿里云文件上传"})
@RequestMapping(value = "/alioss")
@Slf4j
public class AliFileUploadController {


    private final CommonInfoService commonRepository;
    private AmazonS3 amazonS3;

    @Autowired
    public AliFileUploadController(CommonInfoService commonRepository, AmazonS3 amazonS3) {
        this.commonRepository = commonRepository;
        this.amazonS3 = amazonS3;
    }

    @GetMapping(value = "/getCredentials")
    @ApiOperation("获取上传临时凭证")
    public Result getCredentials() {
        try {
            com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
                    // 必填，请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
//                .setAccessKeyId("LTAI5tDzyrWMT2YYTMkUXdpy")
                    .setAccessKeyId(commonRepository.findOne(69).getValue())
                    // 必填，请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
                    .setAccessKeySecret(commonRepository.findOne(70).getValue());
//                    .setAccessKeySecret("ssOeOi4IsIrsbtiyWW4tWOYbjbO0Kp");
            // Endpoint 请参考 https://api.aliyun.com/product/Sts
            config.endpoint = commonRepository.findOne(66).getValue();

            com.aliyun.sts20150401.Client client = new com.aliyun.sts20150401.Client(config);
            com.aliyun.sts20150401.models.AssumeRoleRequest assumeRoleRequest = new com.aliyun.sts20150401.models.AssumeRoleRequest();
            assumeRoleRequest.setRoleArn(commonRepository.findOne(67).getValue());
            assumeRoleRequest.setRoleSessionName("test");
            com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
            // 复制代码运行请自行打印 API 的返回值
            AssumeRoleResponse response = client.assumeRoleWithOptions(assumeRoleRequest, runtime);
            return new Result().put("data",response.getBody().getCredentials());
        } catch (TeaException error) {
            return Result.error(error.getMessage());
            // 诊断地址
//            System.out.println(error.getData().get("Recommend"));
//            com.aliyun.teautil.Common.assertAsString(error.message);
        } catch (Exception _error) {
            return Result.error(_error.getMessage());
//            TeaException error = new TeaException(_error.getMessage(), _error);
//            // 此处仅做打印展示，请谨慎对待异常处理，在工程项目中切勿直接忽略异常。
//            // 诊断地址
//            System.out.println(error.getData().get("Recommend"));
//            com.aliyun.teautil.Common.assertAsString(error.message);
        }
    }


    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    @ApiOperation("文件上传")
    @ResponseBody
    public Result upload(@RequestParam("file") MultipartFile file){
        String value = commonRepository.findOne(234).getValue();
        if("1".equals(value)){
            // 创建OSSClient实例。
            OSS ossClient = new OSSClientBuilder().build(commonRepository.findOne(68).getValue(), commonRepository.findOne(69).getValue(), commonRepository.findOne(70).getValue());
            String suffix = file.getOriginalFilename().substring(Objects.requireNonNull(file.getOriginalFilename()).lastIndexOf("."));
            // 上传文件流。
            InputStream inputStream = null;
            try {
                inputStream =new ByteArrayInputStream(file.getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }
            String completePath=getPath(suffix);
            ossClient.putObject(commonRepository.findOne(71).getValue(), completePath, inputStream);
            // 关闭OSSClient。
            ossClient.shutdown();
            String src = commonRepository.findOne(72).getValue()+"/"+completePath;
            return Result.success().put("data",src);
        }else if("2".equals(value)){
            String accessKey=commonRepository.findOne(800).getValue();
            String secretKey=commonRepository.findOne(801).getValue();
            String bucket=commonRepository.findOne(802).getValue();
            // bucket的命名规则为{name}-{appid} ，此处填写的存储桶名称必须为此格式
            String path=commonRepository.findOne(804).getValue();
            String bucketName=commonRepository.findOne(803).getValue();
            String oldFileName = file.getOriginalFilename();
            String eName = oldFileName.substring(oldFileName.lastIndexOf("."));
            String newFileName = UUID.randomUUID()+eName;
            Calendar cal = Calendar.getInstance();
            int year = cal.get(Calendar.YEAR);
            int month=cal.get(Calendar.MONTH);
            int day=cal.get(Calendar.DATE);
            // 1 初始化用户身份信息(secretId, secretKey)
            COSCredentials cred = new BasicCOSCredentials(accessKey, secretKey);
            // 2 设置bucket的区域, COS地域的简称请参照 https://cloud.tencent.com/document/product/436/6224
            ClientConfig clientConfig = new ClientConfig(new Region(bucket));
            // 3 生成cos客户端
            COSClient cosclient = new COSClient(cred, clientConfig);


            // 简单文件上传, 最大支持 5 GB, 适用于小文件上传, 建议 20 M 以下的文件使用该接口
            // 大文件上传请参照 API 文档高级 API 上传
            File localFile = null;
            try {
                localFile = File.createTempFile("temp",null);
                file.transferTo(localFile);
                // 指定要上传到 COS 上的路径
                String key = "/duanju/"+year+"/"+month+"/"+day+"/"+newFileName;
                PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, localFile);
                PutObjectResult putObjectResult = cosclient.putObject(putObjectRequest);
                return Result.success().put("data",path + putObjectRequest.getKey());
            } catch (IOException e) {
                return Result.error(-100,"文件上传失败！");
            }finally {
                // 关闭客户端(关闭后台线程)
                cosclient.shutdown();
            }
        }else if("3".equals(value)){
            String suffix = file.getOriginalFilename().substring(Objects.requireNonNull(file.getOriginalFilename()).lastIndexOf("."));
            // 上传文件流。
            InputStream inputStream = null;
            try {
                inputStream =new ByteArrayInputStream(file.getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }
            String completePath=getPath(suffix);
            String bucket=commonRepository.findOne(810).getValue();
            com.amazonaws.services.s3.model.PutObjectRequest putObjectRequest = new com.amazonaws.services.s3.model.PutObjectRequest(bucket, completePath, inputStream, new ObjectMetadata());

            putObjectRequest.setCannedAcl(CannedAccessControlList.PublicRead);

            com.amazonaws.services.s3.model.PutObjectResult putObjectResult = amazonS3.putObject(putObjectRequest);

            IOUtils.closeQuietly(inputStream);
            return Result.success().put("data",commonRepository.findOne(811).getValue()+"/"+completePath);
        }else if("4".equals(value)){
            String endpoint = "tos-cn-beijing.volces.com";
            String region = "cn-beijing";
            String accessKey = commonRepository.findOne(888).getValue();
            String secretKey = commonRepository.findOne(889).getValue();

            String bucketName = commonRepository.findOne(890).getValue();
            // 对象名，模拟 example_dir 下的 example_object.txt 文件
            String oldFileName = file.getOriginalFilename();
            String eName = oldFileName.substring(oldFileName.lastIndexOf("."));

            String newFileName = UUID.randomUUID()+eName;
            Calendar cal = Calendar.getInstance();
            int year = cal.get(Calendar.YEAR);
            int month=cal.get(Calendar.MONTH);
            int day=cal.get(Calendar.DATE);

            String objectKey = "duanju/"+year+"/"+month+"/"+day+"/"+newFileName;


            TOSV2 tos = new TOSV2ClientBuilder().build(region, endpoint, accessKey, secretKey);
            FileInputStream fileInputStream = null;
            try {
                File tempFile = File.createTempFile("temp", null);
                file.transferTo(tempFile);
                fileInputStream =new FileInputStream(tempFile);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            try {
                PutObjectFromFileInput putObjectInput = new PutObjectFromFileInput()
                        .setBucket(bucketName).setKey(objectKey).setFileInputStream(fileInputStream);
                tos.putObjectFromFile(putObjectInput);
                return Result.success().put("data",commonRepository.findOne(891).getValue()+"/"+objectKey);
            }  catch (Exception e) {
                log.error("抖音云上传报错："+e.getMessage(),e);
            }
        }else {
            try
            {
                String http = commonRepository.findOne(19).getValue();
                String[] split = http.split("://");
                // 上传文件路径
                String filePath ="/www/wwwroot/"+split[1]+"/file/uploadPath";
                // 上传并返回新文件名称
                String fileName = FileUploadUtils.upload(filePath, file);
                String url = http +fileName;
                return Result.success().put("data",url);
            }
            catch (Exception e)
            {
                log.error("本地上传失败："+e.getMessage(),e);
                return Result.error(-100,"文件上传失败！");
            }
        }
        return Result.error(-100,"文件上传失败！");
    }

    @RequestMapping(value = "/uploadUniApp", method = RequestMethod.POST)
    @ApiOperation("文件上传")
    @ResponseBody
    public String uploadUniApp(@RequestParam("file") MultipartFile file){
        String value = commonRepository.findOne(234).getValue();
        if("1".equals(value)){
            // 创建OSSClient实例。
            OSS ossClient = new OSSClientBuilder().build(commonRepository.findOne(68).getValue(), commonRepository.findOne(69).getValue(), commonRepository.findOne(70).getValue());
            String suffix = file.getOriginalFilename().substring(Objects.requireNonNull(file.getOriginalFilename()).lastIndexOf("."));
            // 上传文件流。
            InputStream inputStream = null;
            try {
                inputStream =new ByteArrayInputStream(file.getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }
            String completePath=getPath(suffix);
            ossClient.putObject(commonRepository.findOne(71).getValue(), completePath, inputStream);
            // 关闭OSSClient。
            ossClient.shutdown();
            return commonRepository.findOne(72).getValue()+"/"+completePath;
        }else if("2".equals(value)){
            String accessKey=commonRepository.findOne(800).getValue();
            String secretKey=commonRepository.findOne(801).getValue();
            String bucket=commonRepository.findOne(802).getValue();
            // bucket的命名规则为{name}-{appid} ，此处填写的存储桶名称必须为此格式
            String path=commonRepository.findOne(804).getValue();
            String bucketName=commonRepository.findOne(803).getValue();
            String oldFileName = file.getOriginalFilename();
            String eName = oldFileName.substring(oldFileName.lastIndexOf("."));
            String newFileName = UUID.randomUUID()+eName;
            Calendar cal = Calendar.getInstance();
            int year = cal.get(Calendar.YEAR);
            int month=cal.get(Calendar.MONTH);
            int day=cal.get(Calendar.DATE);
            // 1 初始化用户身份信息(secretId, secretKey)
            COSCredentials cred = new BasicCOSCredentials(accessKey, secretKey);
            // 2 设置bucket的区域, COS地域的简称请参照 https://cloud.tencent.com/document/product/436/6224
            ClientConfig clientConfig = new ClientConfig(new Region(bucket));
            // 3 生成cos客户端
            COSClient cosclient = new COSClient(cred, clientConfig);


            // 简单文件上传, 最大支持 5 GB, 适用于小文件上传, 建议 20 M 以下的文件使用该接口
            // 大文件上传请参照 API 文档高级 API 上传
            File localFile = null;
            try {
                localFile = File.createTempFile("temp",null);
                file.transferTo(localFile);
                // 指定要上传到 COS 上的路径
                String key = "/duanju/"+year+"/"+month+"/"+day+"/"+newFileName;
                PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, localFile);
                PutObjectResult putObjectResult = cosclient.putObject(putObjectRequest);
                return path + putObjectRequest.getKey();
            } catch (IOException e) {
                return null;
            }finally {
                // 关闭客户端(关闭后台线程)
                cosclient.shutdown();
            }
        }else if("3".equals(value)){
            String suffix = file.getOriginalFilename().substring(Objects.requireNonNull(file.getOriginalFilename()).lastIndexOf("."));
            // 上传文件流。
            InputStream inputStream = null;
            try {
                inputStream =new ByteArrayInputStream(file.getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }
            String completePath=getPath(suffix);
            String bucket=commonRepository.findOne(810).getValue();
            com.amazonaws.services.s3.model.PutObjectRequest putObjectRequest = new com.amazonaws.services.s3.model.PutObjectRequest(bucket, completePath, inputStream, new ObjectMetadata());

            putObjectRequest.setCannedAcl(CannedAccessControlList.PublicRead);

            com.amazonaws.services.s3.model.PutObjectResult putObjectResult = amazonS3.putObject(putObjectRequest);

            IOUtils.closeQuietly(inputStream);
            return commonRepository.findOne(811).getValue()+"/"+completePath;
        }else if("4".equals(value)){
            String endpoint = "tos-cn-beijing.volces.com";
            String region = "cn-beijing";
            String accessKey = commonRepository.findOne(888).getValue();
            String secretKey = commonRepository.findOne(889).getValue();

            String bucketName = commonRepository.findOne(890).getValue();
            // 对象名，模拟 example_dir 下的 example_object.txt 文件
            String oldFileName = file.getOriginalFilename();
            String eName = oldFileName.substring(oldFileName.lastIndexOf("."));

            String newFileName = UUID.randomUUID()+eName;
            Calendar cal = Calendar.getInstance();
            int year = cal.get(Calendar.YEAR);
            int month=cal.get(Calendar.MONTH);
            int day=cal.get(Calendar.DATE);

            String objectKey = "duanju/"+year+"/"+month+"/"+day+"/"+newFileName;


            TOSV2 tos = new TOSV2ClientBuilder().build(region, endpoint, accessKey, secretKey);
            FileInputStream fileInputStream = null;
            try {
                File tempFile = File.createTempFile("temp", null);
                file.transferTo(tempFile);
                fileInputStream =new FileInputStream(tempFile);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            try {
                PutObjectFromFileInput putObjectInput = new PutObjectFromFileInput()
                        .setBucket(bucketName).setKey(objectKey).setFileInputStream(fileInputStream);
                tos.putObjectFromFile(putObjectInput);
                return commonRepository.findOne(891).getValue()+"/"+objectKey;
            }  catch (Exception e) {
                log.error("抖音云上传报错："+e.getMessage(),e);
            }
        }else{
            try
            {
                String http = commonRepository.findOne(19).getValue();
                String[] split = http.split("://");
                // 上传文件路径
                String filePath ="/www/wwwroot/"+split[1]+"/file/uploadPath";
                // 上传并返回新文件名称
                String fileName = FileUploadUtils.upload(filePath, file);
                String url = http +fileName;
                return url;
            }
            catch (Exception e)
            {
                log.error("本地上传失败："+e.getMessage(),e);
                return null;
            }
        }
        return null;
    }



    private String getPath(String suffix) {
        //生成uuid
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        //文件路径
        String path =format(new Date()) + "/" + uuid;
        return path + suffix;
    }


    private String format(Date date) {
        if(date != null){
            SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");
            return df.format(date);
        }
        return null;
    }

    public static void main(String[] args) {
        String endpoint = "tos-cn-beijing.volces.com";
        String region = "cn-beijing";
        String accessKey = "AKLTZTNjZTI2ZWY3YjU1NDUxNTkwYmY1ZmJhNWYxYzQzNjg";
        String secretKey = "WVRWaE9UWmtPV1JtTTJSaU5EWmhORGcxWmpjeE5UUm1OVGt4TVRKbU5tUQ==";

        String bucketName = "tt127764ca8d46e23a01-env-2e02vtd07x";
        // 对象名，模拟 example_dir 下的 example_object.txt 文件
        String objectKey = "duanju/aa1.png";
        // 本地文件路径，请保证文件存在，暂不支持文件夹功能
        String filePath = "E:\\muban2.png";

        TOSV2 tos = new TOSV2ClientBuilder().build(region, endpoint, accessKey, secretKey);

        try {
            PutObjectFromFileInput putObjectInput = new PutObjectFromFileInput()
                    .setBucket(bucketName).setKey(objectKey).setFilePath(filePath);
            PutObjectFromFileOutput output = tos.putObjectFromFile(putObjectInput);
            System.out.println("putObject succeed, object's etag is " + output.getEtag());
            System.out.println("putObject succeed, object's crc64 is " + output.getHashCrc64ecma());
        } catch (TosClientException e) {
            // 操作失败，捕获客户端异常，一般情况是请求参数错误，此时请求并未发送
            System.out.println("putObject failed");
            System.out.println("Message: " + e.getMessage());
            if (e.getCause() != null) {
                e.getCause().printStackTrace();
            }
        } catch (TosServerException e) {
            // 操作失败，捕获服务端异常，可以获取到从服务端返回的详细错误信息
            System.out.println("putObject failed");
            System.out.println("StatusCode: " + e.getStatusCode());
            System.out.println("Code: " + e.getCode());
            System.out.println("Message: " + e.getMessage());
            System.out.println("RequestID: " + e.getRequestID());
        } catch (Throwable t) {
            // 作为兜底捕获其他异常，一般不会执行到这里
            System.out.println("putObject failed");
            System.out.println("unexpected exception, message: " + t.getMessage());
        }
    }






}