package com.ruoyi.common.utils.file;

import com.ruoyi.common.config.MinioConfig;
import io.minio.BucketExistsArgs;
import io.minio.GetObjectArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
import io.minio.SetBucketPolicyArgs;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * MinIO工具类
 * 
 * @author ruoyi
 */
@Component
public class MinioUtils
{
    @Autowired
    private MinioConfig minioConfig;

    private MinioClient minioClient;

    /**
     * 初始化MinIO客户端
     */
    private MinioClient getMinioClient() {
        if (minioClient == null) {
            minioClient = MinioClient.builder()
                    .endpoint(minioConfig.getEndpoint())
                    .credentials(minioConfig.getAccessKey(), minioConfig.getSecretKey())
                    .build();
        }
        return minioClient;
    }

    /**
     * 确保存储桶存在
     */
    public void ensureBucketExists() throws Exception {
        MinioClient client = getMinioClient();
        boolean exists = client.bucketExists(BucketExistsArgs.builder()
                .bucket(minioConfig.getBucketName())
                .build());
        if (!exists) {
            client.makeBucket(MakeBucketArgs.builder()
                    .bucket(minioConfig.getBucketName())
                    .build());
            setBucketPublicRead();
        } else {
            setBucketPublicRead();
        }
    }

    /**
     * 设置bucket为公开读取
     */
    private void setBucketPublicRead() throws Exception {
        String policy = "{\n" +
                "  \"Version\": \"2012-10-17\",\n" +
                "  \"Statement\": [\n" +
                "    {\n" +
                "      \"Effect\": \"Allow\",\n" +
                "      \"Principal\": {\"AWS\": [\"*\"]},\n" +
                "      \"Action\": [\"s3:GetObject\"],\n" +
                "      \"Resource\": [\"arn:aws:s3:::" + minioConfig.getBucketName() + "/*\"]\n" +
                "    }\n" +
                "  ]\n" +
                "}";
        MinioClient client = getMinioClient();
        client.setBucketPolicy(SetBucketPolicyArgs.builder()
                .bucket(minioConfig.getBucketName())
                .config(policy)
                .build());
    }

    /**
     * 上传文件到MinIO
     */
    public String uploadFile(MultipartFile file, String objectName) throws Exception {
        ensureBucketExists();
        MinioClient client = getMinioClient();
        client.putObject(PutObjectArgs.builder()
                .bucket(minioConfig.getBucketName())
                .object(objectName)
                .stream(file.getInputStream(), file.getSize(), -1)
                .contentType(file.getContentType())
                .build());
        return minioConfig.getEndpoint() + "/" + minioConfig.getBucketName() + "/" + objectName;
    }

    /**
     * 从MinIO下载文件
     */
    public void downloadFile(String objectName, HttpServletResponse response) throws Exception {
        MinioClient client = getMinioClient();
        try (InputStream inputStream = client.getObject(GetObjectArgs.builder()
                .bucket(minioConfig.getBucketName())
                .object(objectName)
                .build());
             OutputStream outputStream = response.getOutputStream()) {
            byte[] buffer = new byte[1024];
            int len;
            while ((len = inputStream.read(buffer)) > 0) {
                outputStream.write(buffer, 0, len);
            }
        }
    }

    /**
     * 从MinIO删除文件
     */
    public void deleteFile(String objectName) throws Exception {
        MinioClient client = getMinioClient();
        client.removeObject(RemoveObjectArgs.builder()
                .bucket(minioConfig.getBucketName())
                .object(objectName)
                .build());
    }

    /**
     * 获取MinIO配置
     */
    public MinioConfig getMinioConfig() {
        return minioConfig;
    }
}
