package org.xyzh.file.strategy.impl;

import io.minio.*;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;
import org.xyzh.file.strategy.FileStorageStrategy;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.TimeUnit;

/**
 * @description MinIO文件存储策略实现
 * @filename MinIOFileStorageStrategy.java
 * @author yslg
 * @copyright xyzh
 * @since 2025-10-16
 */
@Slf4j
public class MinIOFileStorageStrategy implements FileStorageStrategy {

    private final String bucketName;
    private final MinioClient minioClient;

    public MinIOFileStorageStrategy(String endpoint, String accessKey, String secretKey, String bucketName) {
        this.bucketName = bucketName;
        
        // 初始化MinIO客户端
        this.minioClient = MinioClient.builder()
                .endpoint(endpoint)
                .credentials(accessKey, secretKey)
                .build();
        
        // 检查并创建bucket
        try {
            boolean bucketExists = minioClient.bucketExists(
                    BucketExistsArgs.builder().bucket(bucketName).build()
            );
            if (!bucketExists) {
                minioClient.makeBucket(
                        MakeBucketArgs.builder().bucket(bucketName).build()
                );
                log.info("创建MinIO Bucket成功: {}", bucketName);
            }
            log.info("初始化MinIO存储策略: endpoint={}, bucket={}", endpoint, bucketName);
        } catch (Exception e) {
            log.error("初始化MinIO失败", e);
            throw new RuntimeException("初始化MinIO失败: " + e.getMessage(), e);
        }
    }

    @Override
    public String upload(MultipartFile file, String fileName, String module) throws IOException {
        try {
            String objectName = module + "/" + fileName;
            
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .stream(file.getInputStream(), file.getSize(), -1)
                            .contentType(file.getContentType())
                            .build()
            );
            
            log.info("文件上传MinIO成功: {}", objectName);
            return objectName;
        } catch (Exception e) {
            log.error("MinIO文件上传失败", e);
            throw new IOException("MinIO文件上传失败: " + e.getMessage(), e);
        }
    }

    @Override
    public byte[] download(String filePath) throws IOException {
        try {
            InputStream stream = minioClient.getObject(
                    GetObjectArgs.builder()
                            .bucket(bucketName)
                            .object(filePath)
                            .build()
            );
            
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = stream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            
            return outputStream.toByteArray();
        } catch (Exception e) {
            log.error("MinIO文件下载失败", e);
            throw new IOException("MinIO文件下载失败: " + e.getMessage(), e);
        }
    }

    @Override
    public boolean delete(String filePath) throws IOException {
        try {
            minioClient.removeObject(
                    RemoveObjectArgs.builder()
                            .bucket(bucketName)
                            .object(filePath)
                            .build()
            );
            
            log.info("MinIO文件删除成功: {}", filePath);
            return true;
        } catch (Exception e) {
            log.error("MinIO文件删除失败", e);
            throw new IOException("MinIO文件删除失败: " + e.getMessage(), e);
        }
    }

    @Override
    public String getFileUrl(String filePath) {
        try {
            // 生成7天有效期的预签名URL
            return minioClient.getPresignedObjectUrl(
                    GetPresignedObjectUrlArgs.builder()
                            .method(Method.GET)
                            .bucket(bucketName)
                            .object(filePath)
                            .expiry(7, TimeUnit.DAYS)
                            .build()
            );
        } catch (Exception e) {
            log.error("生成MinIO文件URL失败", e);
            return null;
        }
    }

    @Override
    public String getStorageType() {
        return "minio";
    }
}

