package com.chushang.oss.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.DeleteObjectsRequest;
import com.aliyun.oss.model.DeleteObjectsResult;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.Payer;
import com.chushang.common.core.exception.ResultException;
import com.chushang.common.core.util.StringUtils;
import com.chushang.oss.config.UploadConfig;
import com.chushang.oss.entity.FileSourceInfo;
import com.chushang.oss.service.OssService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 阿里云存储
 */
@Slf4j
@Service("aliOssService")
@ConditionalOnExpression("'${config.oss.storage}'.equals('ali')")
public class AliServiceImpl implements OssService {

    private OSS oss;

    @Resource
    private UploadConfig config;

//    public AliyunUploadStorageService(CloudProperties cloudProperties){
//        this.config = (AliyunProperties) cloudProperties;
//        //初始化
//        init();
//    }

    @PostConstruct
    private void init(){
        oss = new OSSClientBuilder()
                        .build(config.getEndPoint(), config.getAccessKey(), config.getSecretKey());
        Payer payer = Payer.Requester;
        oss.setBucketRequestPayment(config.getBucketName(), payer);
    }

    public String getPrefixPath(String prefix, String filename){
        String aliyunPrefix = config.getPrefix();
        if (StringUtils.isNotEmpty(aliyunPrefix)){
            prefix = aliyunPrefix  + "/" + prefix + "/" + filename;
        }else {
            prefix = prefix + "/" + filename;
        }
        return prefix;
    }

    @Override
    public String upload(InputStream inputStream, FileSourceInfo info) {
        String path = info.getPath();
        try {
            oss.putObject(config.getBucketName(), path, inputStream);
        } catch (Exception e){
            throw new ResultException("上传文件失败，请检查配置信息", e);
        }
        return path;
    }

    @Override
    public void delFile(String path){
        try {
            oss.deleteObject(config.getBucketName(), path);
        } catch (Exception e){
            throw new ResultException("删除文件失败，请检查配置信息", e);
        }
    }

    public List<String> delFileBatch(List<String> keys){
        if (CollectionUtil.isEmpty(keys)) return new ArrayList<>();
        try {
            // 批量删除
            DeleteObjectsRequest objectsRequest = new DeleteObjectsRequest(config.getBucketName());

            objectsRequest.setKeys(keys);
            objectsRequest.setQuiet(true);
            objectsRequest.setEncodingType("url");

            DeleteObjectsResult deleteObjectsResult = oss.deleteObjects(objectsRequest);
            // 这些是成功删除对象的key
            List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();


            Iterator<String> iterator = keys.iterator();
            List<String> results = new ArrayList<>();
            while (iterator.hasNext()){
                String key = iterator.next();
                if (deletedObjects.contains(key)){
                    iterator.remove();
                }else {
                    results.add(key);
                }
            }
            if (CollectionUtil.isNotEmpty(results)){
                log.error("以下文件未从oss 中成功删除 : {}", results);
                return results;
            }
        } catch (Exception e){
            throw new ResultException("删除文件失败，请检查配置信息", e);
        }
        return new ArrayList<>();
    }
//
//    @Override
//    public InputStream getFileStream(FileSourceInfo info) {
//        OSSObject object = oss.getObject(config.getBucketName(), info.getPath());
//        return object.getObjectContent();
//    }

    @Override
    public byte[] getFileBytes(FileSourceInfo info) {
        OSSObject object = oss.getObject(config.getBucketName(), info.getPath());
        InputStream is = object.getObjectContent();
        try (ByteArrayOutputStream buffer = new ByteArrayOutputStream()){
            int nRead;
            byte[] data = new byte[1024];
            while ((nRead = is.read(data, 0, data.length)) != -1) {
                buffer.write(data, 0, nRead);
            }
            buffer.flush();
            return buffer.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}

