package com.zhentao.service.impl;

import com.zhentao.service.MinioService;
import io.minio.*;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.UUID;

/**
 * MinIO服务实现类
 */
@Slf4j
@Service
public class MinioServiceImpl implements MinioService {
    
    @Autowired
    private MinioClient minioClient;
    
    @Value("${minio.endpoint}")
    private String endpoint;
    
    @Value("${minio.bucketName}")
    private String bucketName;
    
    @Override
    public String uploadImage(MultipartFile file) throws Exception {
        log.info("========== 开始上传图片到MinIO ==========");
        log.info("文件名: {}", file.getOriginalFilename());
        log.info("文件大小: {} bytes", file.getSize());
        log.info("文件类型: {}", file.getContentType());
        
        // 确保bucket存在
        ensureBucketExists();
        
        // 生成唯一文件名
        String originalFilename = file.getOriginalFilename();
        String extension = originalFilename != null && originalFilename.contains(".")
                ? originalFilename.substring(originalFilename.lastIndexOf("."))
                : ".jpg";
        String fileName = "images/" + UUID.randomUUID().toString() + extension;
        
        log.info("生成的对象名称: {}", fileName);
        
        // 将文件转为byte数组，避免流被提前关闭
        byte[] fileBytes = file.getBytes();
        InputStream inputStream = new ByteArrayInputStream(fileBytes);
        
        // 上传到MinIO
        minioClient.putObject(
            PutObjectArgs.builder()
                .bucket(bucketName)
                .object(fileName)
                .stream(inputStream, fileBytes.length, -1)
                .contentType(file.getContentType())
                .build()
        );
        
        log.info("✓ 文件上传成功");
        
        // 返回访问URL（公共访问）
        String imageUrl = endpoint + "/" + bucketName + "/" + fileName;
        log.info("图片访问URL: {}", imageUrl);
        
        return imageUrl;
    }
    
    @Override
    public String uploadFile(MultipartFile file) throws Exception {
        log.info("========== 开始上传文件到MinIO ==========");
        log.info("文件名: {}", file.getOriginalFilename());
        log.info("文件大小: {} bytes", file.getSize());
        
        // 确保bucket存在
        ensureBucketExists();
        
        // 生成唯一文件名
        String originalFilename = file.getOriginalFilename();
        String extension = originalFilename != null && originalFilename.contains(".")
                ? originalFilename.substring(originalFilename.lastIndexOf("."))
                : "";
        String fileName = "files/" + UUID.randomUUID().toString() + extension;
        
        log.info("生成的对象名称: {}", fileName);
        
        // 将文件转为byte数组
        byte[] fileBytes = file.getBytes();
        InputStream inputStream = new ByteArrayInputStream(fileBytes);
        
        // 上传到MinIO
        minioClient.putObject(
            PutObjectArgs.builder()
                .bucket(bucketName)
                .object(fileName)
                .stream(inputStream, fileBytes.length, -1)
                .contentType(file.getContentType())
                .build()
        );
        
        log.info("✓ 文件上传成功");
        
        // 返回访问URL
        String fileUrl = endpoint + "/" + bucketName + "/" + fileName;
        log.info("文件访问URL: {}", fileUrl);
        
        return fileUrl;
    }
    
    @Override
    public void deleteFile(String fileUrl) throws Exception {
        if (fileUrl == null || fileUrl.isEmpty()) {
            return;
        }
        
        try {
            // 从URL中提取对象名称
            String objectName = fileUrl.substring(fileUrl.indexOf(bucketName) + bucketName.length() + 1);
            
            log.info("删除MinIO文件: {}", objectName);
            
            minioClient.removeObject(
                RemoveObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .build()
            );
            
            log.info("✓ 文件删除成功");
        } catch (Exception e) {
            log.error("删除文件失败: {}", e.getMessage());
            throw e;
        }
    }
    
    @Override
    public void ensureBucketExists() throws Exception {
        try {
            boolean exists = minioClient.bucketExists(
                BucketExistsArgs.builder()
                    .bucket(bucketName)
                    .build()
            );
            
            if (!exists) {
                log.info("Bucket不存在，正在创建: {}", bucketName);
                
                // 创建bucket
                minioClient.makeBucket(
                    MakeBucketArgs.builder()
                        .bucket(bucketName)
                        .build()
                );
                
                log.info("✓ Bucket创建成功");
                
                // 设置bucket为公开访问
                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:::" + bucketName + "/*\"]\n" +
                        "    }\n" +
                        "  ]\n" +
                        "}";
                
                minioClient.setBucketPolicy(
                    SetBucketPolicyArgs.builder()
                        .bucket(bucketName)
                        .config(policy)
                        .build()
                );
                
                log.info("✓ Bucket权限设置成功（公开访问）");
            } else {
                log.info("Bucket已存在: {}", bucketName);
            }
        } catch (Exception e) {
            log.error("检查/创建Bucket失败: {}", e.getMessage());
            throw e;
        }
    }
}

