package com.artfess.file.attachmentService;

import cn.hutool.core.io.IoUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.OSSObject;
import com.artfess.base.attachment.Attachment;
import com.artfess.base.attachment.AttachmentService;
import com.artfess.base.util.AppUtil;
import com.artfess.base.util.BeanUtils;
import com.artfess.base.util.StringUtil;
import com.artfess.file.config.AliyunOssSettings;
import com.artfess.file.model.FileStorage;
import com.artfess.file.model.FlowUploadProperties;
import com.artfess.file.params.FlowUploadPropertiesStorageDTO;
import com.artfess.file.persistence.manager.FileStorageManager;
import com.artfess.file.persistence.manager.FlowUploadPropertiesManager;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Paths;

@Service
public class AliyunOssAttachmentServiceImpl implements AttachmentService {
    private AliyunOssSettings initOssSettings(Attachment attachment, String propertiesId) {
        AliyunOssSettings ossSettings = AppUtil.getBean(AliyunOssSettings.class);
        setObjectKeyAndFilePath(attachment, ossSettings);
        if (StringUtil.isNotEmpty(propertiesId)) {
            FileStorageManager fileStorageManager = AppUtil.getBean(FileStorageManager.class);
            FileStorage fileStorage = fileStorageManager.get(propertiesId);
            if (BeanUtils.isNotEmpty(fileStorage)) {
                ossSettings.setEndpoint(fileStorage.getEndpoint());
                ossSettings.setAccessKeyId(fileStorage.getAccessKeyId());
                ossSettings.setAccessKeySecret(fileStorage.getAccessKeySecret());
                ossSettings.setBucketName(fileStorage.getLocation());
                attachment.setEntryptName(fileStorage.getEncryptName() == 0 ? false : true);
                setObjectKeyAndFilePath(attachment, ossSettings);
                return ossSettings;
            }else{
                FlowUploadPropertiesManager uploadPropertiesManager = AppUtil.getBean(FlowUploadPropertiesManager.class);
                FlowUploadPropertiesStorageDTO uploadProperties = uploadPropertiesManager.getById(propertiesId);
                if (BeanUtils.isNotEmpty(uploadProperties)) {
                    ossSettings.setEndpoint(uploadProperties.getEndpoint());
                    ossSettings.setAccessKeyId(uploadProperties.getAccessKeyId());
                    ossSettings.setAccessKeySecret(uploadProperties.getAccessKeySecret());
                    ossSettings.setBucketName(uploadProperties.getLocation());
                    attachment.setEntryptName(uploadProperties.getEncryptName() == 0 ? false : true);
                    setObjectKeyAndFilePath(attachment, ossSettings);
                    return ossSettings;
                }
            }
        }
        return ossSettings;
    }

    // 设置 ossSettings 的 objectKey和 attachment 的 filePath
    private void setObjectKeyAndFilePath(Attachment attachment, AliyunOssSettings ossSettings) {
        String fileParentPath = "";
        String filePath = attachment.getFilePath();
        if (StringUtil.isNotEmpty(filePath)) {
            fileParentPath = Paths.get(filePath).getParent().toString();
            fileParentPath = fileParentPath.replaceAll("\\\\", "/");
            if (fileParentPath.startsWith("/")) {
                fileParentPath = fileParentPath.substring(1);
            }
        }
        if (attachment.getEntryptName()) {
            filePath = fileParentPath + "/" + attachment.getId() + "." + attachment.getExtensionName();
        } else {
            filePath = fileParentPath + "/" + attachment.getId() + "_" + attachment.getFileName() + "." + attachment.getExtensionName();
        }
        ossSettings.setObjectKey(filePath);
        attachment.setFilePath(filePath);
    }

    @Override
    public void remove(Attachment attachment, String propertiesId) throws Exception {
        AliyunOssSettings ossSettings = initOssSettings(attachment, propertiesId);
        OSS ossClient = new OSSClientBuilder().build(ossSettings.getEndpoint(), ossSettings.getAccessKeyId(), ossSettings.getAccessKeySecret());
        try {
            if (!ossClient.doesBucketExist(ossSettings.getBucketName())) {
                ossClient.createBucket(ossSettings.getBucketName());
            }
            ossClient.deleteObject(ossSettings.getBucketName(), ossSettings.getObjectKey());
        } finally {
            ossClient.shutdown();
        }
    }

    @Override
    public void upload(Attachment attachment, InputStream inputStream, String propertiesId) throws Exception {
        AliyunOssSettings ossSettings = initOssSettings(attachment, propertiesId);
        OSS ossClient = new OSSClientBuilder().build(ossSettings.getEndpoint(), ossSettings.getAccessKeyId(), ossSettings.getAccessKeySecret());
        try {
            if (!ossClient.doesBucketExist(ossSettings.getBucketName())) {
                ossClient.createBucket(ossSettings.getBucketName());
            }
            ossClient.putObject(ossSettings.getBucketName(), ossSettings.getObjectKey(), inputStream);
            String url = "http://" + ossSettings.getBucketName() + "." + ossSettings.getEndpoint() + "/" + ossSettings.getObjectKey();
        } finally {
            inputStream.close();
            ossClient.shutdown();
        }
    }

    @Override
    public void download(Attachment attachment, OutputStream outStream, String propertiesId) throws Exception {
        AliyunOssSettings ossSettings = initOssSettings(attachment, propertiesId);
        OSS ossClient = new OSSClientBuilder().build(ossSettings.getEndpoint(), ossSettings.getAccessKeyId(), ossSettings.getAccessKeySecret());
        try (OSSObject ossObject = ossClient.getObject(ossSettings.getBucketName(), ossSettings.getObjectKey())) {
            if (!ossClient.doesBucketExist(ossSettings.getBucketName())) {
                ossClient.createBucket(ossSettings.getBucketName());
            }
            IoUtil.copy(ossObject.getObjectContent(), outStream);
        } finally {
            outStream.close();
            ossClient.shutdown();
        }
    }

    @Override
    public String getStoreType() {
        return "aliyunOss";
    }


    @Override
    public boolean chekckFile(Attachment attachment, String propertiesId) throws Exception {
        AliyunOssSettings ossSettings = initOssSettings(attachment, propertiesId);
        OSS ossClient = new OSSClientBuilder().build(ossSettings.getEndpoint(), ossSettings.getAccessKeyId(), ossSettings.getAccessKeySecret());
        try {
            if (!ossClient.doesBucketExist(ossSettings.getBucketName())) {
                ossClient.createBucket(ossSettings.getBucketName());
            }
            boolean found = ossClient.doesObjectExist(ossSettings.getBucketName(), ossSettings.getObjectKey());
            return found;
        } finally {
            ossClient.shutdown();
        }
    }

    @Override
    public byte[] getFileBytes(Attachment attachment) throws Exception {
        return null;
    }

    @Override
    public String getUrl(Attachment attachment) {
        return null;
    }

    @Override
    public String initMultiPartUpload(Attachment attachment) {
        return null;
    }

    @Override
    public String getChunkUrl(Attachment attachment, Integer partNumber, String uploadId) {
        return null;
    }

    @Override
    public boolean mergeMultipartUpload(Attachment attachment, String uploadId, int realyPartNumber) {
        return false;
    }
}
