package com.erp.file.service.storage;

import io.minio.*;
import io.minio.http.Method;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

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

/**
 * MinIO存储策略
 */
@Slf4j
@Component
public class MinioStorageStrategy implements StorageStrategy {
    
    @Value("${file.storage.minio.endpoint:}")
    private String endpoint;
    
    @Value("${file.storage.minio.access-key:}")
    private String accessKey;
    
    @Value("${file.storage.minio.secret-key:}")
    private String secretKey;
    
    @Value("${file.storage.minio.bucket-name:erp-files}")
    private String bucketName;
    
    @Value("${file.storage.minio.base-url:}")
    private String baseUrl;
    
    @Value("${file.storage.minio.secure:false}")
    private boolean secure;
    
    private MinioClient minioClient;
    
    @PostConstruct
    @Override
    public void init() {
        if (!isConfigured()) {
            log.warn("MinIO未配置，将不启用该存储策略");
            return;
        }
        this.minioClient = MinioClient.builder()
                .endpoint(endpoint)
                .credentials(accessKey, secretKey)
                .build();
        
        // 确保桶存在
        try {
            boolean bucketExists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (!bucketExists) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
                log.info("MinIO桶创建成功: {}", bucketName);
            }
            log.info("MinIO存储初始化成功，桶: {}", bucketName);
        } catch (Exception e) {
            log.error("MinIO初始化失败", e);
        }
    }
    
    @Override
    public String upload(MultipartFile file, String path, String storageName) {
        ensureClient();
        try {
            String objectName = path + "/" + storageName;
            
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .stream(file.getInputStream(), file.getSize(), -1)
                            .contentType(file.getContentType())
                            .build()
            );
            
            log.info("文件上传至MinIO成功: {}", objectName);
            return getUrl(objectName);
        } catch (IOException e) {
            throw new RuntimeException("MinIO文件上传失败", e);
        } catch (Exception e) {
            throw new RuntimeException("MinIO文件上传失败", e);
        }
    }
    
    @Override
    public InputStream download(String path) {
        ensureClient();
        try {
            return minioClient.getObject(
                    GetObjectArgs.builder()
                            .bucket(bucketName)
                            .object(path)
                            .build()
            );
        } catch (Exception e) {
            throw new RuntimeException("MinIO文件下载失败", e);
        }
    }
    
    @Override
    public void delete(String path) {
        ensureClient();
        try {
            minioClient.removeObject(
                    RemoveObjectArgs.builder()
                            .bucket(bucketName)
                            .object(path)
                            .build()
            );
            log.info("MinIO文件删除成功: {}", path);
        } catch (Exception e) {
            log.error("MinIO文件删除失败: {}", path, e);
            throw new RuntimeException("MinIO文件删除失败", e);
        }
    }
    
    @Override
    public boolean exists(String path) {
        ensureClient();
        try {
            minioClient.statObject(
                    StatObjectArgs.builder()
                            .bucket(bucketName)
                            .object(path)
                            .build()
            );
            return true;
        } catch (Exception e) {
            return false;
        }
    }
    
    @Override
    public String getUrl(String path) {
        if (baseUrl != null && !baseUrl.isEmpty()) {
            return baseUrl + "/" + path;
        }
        try {
            return minioClient.getPresignedObjectUrl(
                    GetPresignedObjectUrlArgs.builder()
                            .method(Method.GET)
                            .bucket(bucketName)
                            .object(path)
                            .expiry(365, TimeUnit.DAYS)
                            .build()
            );
        } catch (Exception e) {
            log.error("生成MinIO URL失败", e);
            return path;
        }
    }
    
    @Override
    public String getFullPath(String path) {
        return bucketName + "/" + path;
    }
    
    @Override
    public String getType() {
        return "minio";
    }
    
    private void ensureClient() {
        if (minioClient == null) {
            throw new RuntimeException("MinIO客户端未初始化，请检查配置");
        }
    }
    
    private boolean isConfigured() {
        return endpoint != null && !endpoint.isEmpty() &&
               accessKey != null && !accessKey.isEmpty() &&
               secretKey != null && !secretKey.isEmpty();
    }
}
