package com.nailart.utils;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;

/**
 * @Description MinIO工具类，提供文件存储操作的封装
 * @Classname MinioUtils
 * @Date 2025/7/16 10:15
 * @Created by 21616
 */
@Component
public class MinioUtils {

    private final MinioClient minioClient;

    @Autowired
    public MinioUtils(MinioClient minioClient) {
        this.minioClient = minioClient;
    }

    /**
     * 检查存储桶是否存在
     * @param bucketName 存储桶名称
     * @return 存在返回true，否则返回false
     * @throws ServerException            服务端异常
     * @throws InsufficientDataException  数据不足异常
     * @throws ErrorResponseException     错误响应异常
     * @throws IOException                IO异常
     * @throws NoSuchAlgorithmException   算法不存在异常
     * @throws InvalidKeyException        无效密钥异常
     * @throws InvalidResponseException   无效响应异常
     * @throws XmlParserException         XML解析异常
     * @throws InternalException          内部异常
     */
    public boolean bucketExists(String bucketName) throws ServerException, InsufficientDataException,
            ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException,
            InvalidResponseException, XmlParserException, InternalException {
        return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
    }

    /**
     * 创建存储桶
     * @param bucketName 存储桶名称
     * @throws ServerException            服务端异常
     * @throws InsufficientDataException  数据不足异常
     * @throws ErrorResponseException     错误响应异常
     * @throws IOException                IO异常
     * @throws NoSuchAlgorithmException   算法不存在异常
     * @throws InvalidKeyException        无效密钥异常
     * @throws InvalidResponseException   无效响应异常
     * @throws XmlParserException         XML解析异常
     * @throws InternalException          内部异常
     */
    public void makeBucket(String bucketName) throws ServerException, InsufficientDataException,
            ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException,
            InvalidResponseException, XmlParserException, InternalException {
        if (!bucketExists(bucketName)) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }
    }

    /**
     * 列出所有存储桶
     * @return 存储桶列表
     * @throws ServerException            服务端异常
     * @throws InsufficientDataException  数据不足异常
     * @throws ErrorResponseException     错误响应异常
     * @throws IOException                IO异常
     * @throws NoSuchAlgorithmException   算法不存在异常
     * @throws InvalidKeyException        无效密钥异常
     * @throws InvalidResponseException   无效响应异常
     * @throws XmlParserException         XML解析异常
     * @throws InternalException          内部异常
     */
    public List<Bucket> listBuckets() throws ServerException, InsufficientDataException,
            ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException,
            InvalidResponseException, XmlParserException, InternalException {
        return minioClient.listBuckets();
    }

    /**
     * 删除存储桶（必须为空桶）
     * @param bucketName 存储桶名称
     * @throws ServerException            服务端异常
     * @throws InsufficientDataException  数据不足异常
     * @throws ErrorResponseException     错误响应异常
     * @throws IOException                IO异常
     * @throws NoSuchAlgorithmException   算法不存在异常
     * @throws InvalidKeyException        无效密钥异常
     * @throws InvalidResponseException   无效响应异常
     * @throws XmlParserException         XML解析异常
     * @throws InternalException          内部异常
     */
    public void removeBucket(String bucketName) throws ServerException, InsufficientDataException,
            ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException,
            InvalidResponseException, XmlParserException, InternalException {
        if (bucketExists(bucketName)) {
            minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
        }
    }

    /**
     * 上传本地文件到MinIO
     * @param bucketName 存储桶名称
     * @param objectName 对象名称（文件路径）
     * @param filePath   本地文件路径
     * @throws ServerException            服务端异常
     * @throws InsufficientDataException  数据不足异常
     * @throws ErrorResponseException     错误响应异常
     * @throws IOException                IO异常
     * @throws NoSuchAlgorithmException   算法不存在异常
     * @throws InvalidKeyException        无效密钥异常
     * @throws InvalidResponseException   无效响应异常
     * @throws XmlParserException         XML解析异常
     * @throws InternalException          内部异常
     */
    public void uploadFile(String bucketName, String objectName, String filePath) throws ServerException,
            InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException,
            InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        minioClient.uploadObject(UploadObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .filename(filePath)
                .build());
    }

    /**
     * 通过InputStream上传文件
     * @param bucketName  存储桶名称
     * @param objectName  对象名称
     * @param inputStream 文件输入流
     * @param contentType 文件内容类型
     * @throws ServerException            服务端异常
     * @throws InsufficientDataException  数据不足异常
     * @throws ErrorResponseException     错误响应异常
     * @throws IOException                IO异常
     * @throws NoSuchAlgorithmException   算法不存在异常
     * @throws InvalidKeyException        无效密钥异常
     * @throws InvalidResponseException   无效响应异常
     * @throws XmlParserException         XML解析异常
     * @throws InternalException          内部异常
     */
    public void uploadFile(String bucketName, String objectName, InputStream inputStream, String contentType)
            throws ServerException, InsufficientDataException, ErrorResponseException, IOException,
            NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException,
            InternalException {
        minioClient.putObject(PutObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .stream(inputStream, inputStream.available(), -1)
                .contentType(contentType)
                .build());
    }

    /**
     * 通过Spring MultipartFile上传文件
     * @param bucketName 存储桶名称
     * @param objectName 对象名称
     * @param file       Spring MultipartFile文件对象
     * @throws ServerException            服务端异常
     * @throws InsufficientDataException  数据不足异常
     * @throws ErrorResponseException     错误响应异常
     * @throws IOException                IO异常
     * @throws NoSuchAlgorithmException   算法不存在异常
     * @throws InvalidKeyException        无效密钥异常
     * @throws InvalidResponseException   无效响应异常
     * @throws XmlParserException         XML解析异常
     * @throws InternalException          内部异常
     */
    public void uploadFile(String bucketName, String objectName, MultipartFile file)
            throws ServerException, InsufficientDataException, ErrorResponseException, IOException,
            NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException,
            InternalException {
        minioClient.putObject(PutObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .stream(file.getInputStream(), file.getSize(), -1)
                .contentType(file.getContentType())
                .build());
    }

    /**
     * 下载文件到本地
     * @param bucketName 存储桶名称
     * @param objectName 对象名称
     * @param filePath   本地文件路径
     * @throws ServerException            服务端异常
     * @throws InsufficientDataException  数据不足异常
     * @throws ErrorResponseException     错误响应异常
     * @throws IOException                IO异常
     * @throws NoSuchAlgorithmException   算法不存在异常
     * @throws InvalidKeyException        无效密钥异常
     * @throws InvalidResponseException   无效响应异常
     * @throws XmlParserException         XML解析异常
     * @throws InternalException          内部异常
     */
    public void downloadFile(String bucketName, String objectName, String filePath) throws ServerException,
            InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException,
            InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        minioClient.downloadObject(DownloadObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .filename(filePath)
                .build());
    }

    /**
     * 获取文件输入流
     * @param bucketName 存储桶名称
     * @param objectName 对象名称
     * @return 文件输入流
     * @throws ServerException            服务端异常
     * @throws InsufficientDataException  数据不足异常
     * @throws ErrorResponseException     错误响应异常
     * @throws IOException                IO异常
     * @throws NoSuchAlgorithmException   算法不存在异常
     * @throws InvalidKeyException        无效密钥异常
     * @throws InvalidResponseException   无效响应异常
     * @throws XmlParserException         XML解析异常
     * @throws InternalException          内部异常
     */
    public InputStream getObject(String bucketName, String objectName) throws ServerException,
            InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException,
            InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        return minioClient.getObject(GetObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .build());
    }

    /**
     * 删除对象
     * @param bucketName 存储桶名称
     * @param objectName 对象名称
     * @throws ServerException            服务端异常
     * @throws InsufficientDataException  数据不足异常
     * @throws ErrorResponseException     错误响应异常
     * @throws IOException                IO异常
     * @throws NoSuchAlgorithmException   算法不存在异常
     * @throws InvalidKeyException        无效密钥异常
     * @throws InvalidResponseException   无效响应异常
     * @throws XmlParserException         XML解析异常
     * @throws InternalException          内部异常
     */
    public void removeObject(String bucketName, String objectName) throws ServerException,
            InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException,
            InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        minioClient.removeObject(RemoveObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .build());
    }

    /**
     * 列出存储桶中的对象
     * @param bucketName 存储桶名称
     * @return 对象迭代器
     */
    public Iterable<Result<Item>> listObjects(String bucketName) {
        return minioClient.listObjects(ListObjectsArgs.builder()
                .bucket(bucketName)
                .build());
    }

    /**
     * 生成预签名URL（用于临时访问私有对象）
     * @param bucketName 存储桶名称
     * @param objectName 对象名称
     * @param expiry     过期时间（秒）
     * @return 预签名URL
     * @throws ServerException            服务端异常
     * @throws InsufficientDataException  数据不足异常
     * @throws ErrorResponseException     错误响应异常
     * @throws IOException                IO异常
     * @throws NoSuchAlgorithmException   算法不存在异常
     * @throws InvalidKeyException        无效密钥异常
     * @throws InvalidResponseException   无效响应异常
     * @throws XmlParserException         XML解析异常
     * @throws InternalException          内部异常
     */
    public String getPresignedUrl(String bucketName, String objectName, int expiry) throws ServerException,
            InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException,
            InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                .method(Method.GET)
                .bucket(bucketName)
                .object(objectName)
                .expiry(expiry)
                .build());
    }
}