package com.starry.admin.common.oss.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.io.FileTypeUtil;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.PutObjectRequest;
import com.starry.admin.common.exception.CustomException;
import com.starry.admin.common.oss.OssProperties;
import com.starry.admin.common.oss.service.IOssFileService;
import com.starry.common.utils.IdUtils;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.stereotype.Service;

/**
 * @author admin
 */
@Service
@Slf4j
public class OssFileServiceImpl implements IOssFileService {

    @Override
    public String upload(InputStream inputStream, String module, String filename) {

        BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
        bufferedInputStream.mark(0);
        String fileType = FileTypeUtil.getType(bufferedInputStream);
        try {
            bufferedInputStream.reset();
        } catch (IOException e) {
            throw new CustomException("文件上传到OSS失败");
        }
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(OssProperties.ENDPOINT, OssProperties.KEY_ID,
                OssProperties.KEY_SECRET);
        log.info("OSSClient实例创建成功");
        try {
            // 判断oss实例是否存在：如果不存在则创建，如果存在则获取
            if (!ossClient.doesBucketExist(OssProperties.BUCKET_NAME)) {
                // 创建bucket
                ossClient.createBucket(OssProperties.BUCKET_NAME);
                log.info("bucket存储空间【{}】创建成功", OssProperties.BUCKET_NAME);
                // 设置oss实例的访问权限：公共读
                ossClient.setBucketAcl(OssProperties.BUCKET_NAME, CannedAccessControlList.PublicRead);
                log.info("【{}】存储空间访问权限设置为公共读成功", OssProperties.BUCKET_NAME);
            }
            // 构建日期路径：avatar/2019/02/26/文件名
            String folder = new DateTime().toString("yyyy/MM/dd");
            // 文件名：uuid.扩展名

            filename = IdUtils.getUuid() + "." + fileType;
            // 文件根路径
            String key = module + "/" + folder + "/" + filename;
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(OssProperties.BUCKET_NAME, key,
                    bufferedInputStream);
            // 创建PutObject请求。
            ossClient.putObject(putObjectRequest);
            log.info("oss文件上传成功");
            // 阿里云文件绝对路径
            String endpoint = OssProperties.ENDPOINT;
            if (OssProperties.ENDPOINT.contains("//")) {
                endpoint = OssProperties.ENDPOINT.substring(OssProperties.ENDPOINT.lastIndexOf("//") + 2);
            }
            // 返回文件的访问路径
            return "https://" + OssProperties.BUCKET_NAME + "." + endpoint + "/" + key;
        } catch (OSSException oe) {
            log.error("OSSException 文件上传失败：", oe);
            throw new CustomException("OSS文件上传异常,{}" + oe.getMessage());
        } catch (ClientException ce) {
            log.error("ClientException 文件上传失败：{}", ExceptionUtils.getStackTrace(ce));
            throw new CustomException("OSS文件上传异常,{}" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
                log.info("关闭ossClient");
            }
        }
    }

    @Override
    public void remove(String url) {
        OSS ossClient = new OSSClientBuilder().build(OssProperties.ENDPOINT, OssProperties.KEY_ID,
                OssProperties.KEY_SECRET);
        log.info("OSSClient实例创建成功");
        try {
            String endpoint = OssProperties.ENDPOINT.substring(OssProperties.ENDPOINT.lastIndexOf("//") + 2);
            // 文件名（服务器上的文件路径）
            String host = "https://" + OssProperties.BUCKET_NAME + "." + endpoint + "/";
            String objectName = url.substring(host.length());
            // 删除文件或目录。如果要删除目录，目录必须为空。
            ossClient.deleteObject(OssProperties.BUCKET_NAME, objectName);
            log.info("{}文件删除成功", objectName);
        } catch (OSSException oe) {
            log.error("OSSException 文件删除失败", oe);
            throw new CustomException("OSS文件删除异常,{}" + oe.getMessage());
        } catch (ClientException ce) {
            log.error("ClientException 文件删除失败：{}", ExceptionUtils.getStackTrace(ce));
            throw new CustomException("OSS文件删除异常,{}" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                // 关闭OSSClient。
                ossClient.shutdown();
                log.info("关闭ossClient");
            }
        }
    }

}
