package com.nailart.service.impl;
import com.nailart.service.FileStorageService;
import com.nailart.utils.MinioUtils;
import io.minio.Result;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
/**
 * @Description MinIO 文件存储服务实现
 * @Classname FileStorageServiceImpl
 * @Date 2025/7/19 17:20
 * @Created by 21616
 */
@Service
public class FileStorageServiceImpl implements FileStorageService {

    private static final Logger logger = LoggerFactory.getLogger(FileStorageServiceImpl.class);
    private final MinioUtils minioUtils;

    @Autowired
    public FileStorageServiceImpl(MinioUtils minioUtils) {
        this.minioUtils = minioUtils;
    }

    @Override
    public String uploadFile(String bucketName, String filePath, MultipartFile file) {
        try {
            ensureBucketExists(bucketName);
            minioUtils.uploadFile(bucketName, filePath, file);
            logger.info("文件上传成功: bucket={}, path={}", bucketName, filePath);
            return filePath;
        } catch (Exception e) {
            logger.error("文件上传失败: bucket={}, path={}", bucketName, filePath, e);
            throw new RuntimeException("文件上传失败", e);
        }
    }

    @Override
    public String uploadFile(String bucketName, String filePath, InputStream inputStream, String contentType) {
        try {
            ensureBucketExists(bucketName);
            minioUtils.uploadFile(bucketName, filePath, inputStream, contentType);
            logger.info("文件上传成功: bucket={}, path={}", bucketName, filePath);
            return filePath;
        } catch (Exception e) {
            logger.error("文件上传失败: bucket={}, path={}", bucketName, filePath, e);
            throw new RuntimeException("文件上传失败", e);
        }
    }

    @Override
    public InputStream downloadFile(String bucketName, String filePath) {
        try {
            if (!fileExists(bucketName, filePath)) {
                logger.warn("文件不存在: bucket={}, path={}", bucketName, filePath);
                throw new RuntimeException("文件不存在");
            }
            return minioUtils.getObject(bucketName, filePath);
        } catch (Exception e) {
            logger.error("文件下载失败: bucket={}, path={}", bucketName, filePath, e);
            throw new RuntimeException("文件下载失败", e);
        }
    }

    @Override
    public void deleteFile(String bucketName, String filePath) {
        try {
            if (!fileExists(bucketName, filePath)) {
                logger.warn("文件不存在，无需删除: bucket={}, path={}", bucketName, filePath);
                return;
            }
            minioUtils.removeObject(bucketName, filePath);
            logger.info("文件删除成功: bucket={}, path={}", bucketName, filePath);
        } catch (Exception e) {
            logger.error("文件删除失败: bucket={}, path={}", bucketName, filePath, e);
            throw new RuntimeException("文件删除失败", e);
        }
    }

    @Override
    public boolean fileExists(String bucketName, String filePath) {
        try {
            if (!bucketExists(bucketName)) {
                return false;
            }
            // 通过列出对象检查文件是否存在
            Iterable<Result<Item>> results = minioUtils.listObjects(bucketName);
            return StreamSupport.stream(results.spliterator(), false)
                    .anyMatch(itemResult -> {
                        try {
                            return itemResult.get().objectName().equals(filePath);
                        } catch (Exception e) {
                            logger.error("检查文件存在时出错", e);
                            return false;
                        }
                    });
        } catch (Exception e) {
            logger.error("检查文件存在失败: bucket={}, path={}", bucketName, filePath, e);
            throw new RuntimeException("检查文件存在失败", e);
        }
    }

    @Override
    public String getFileUrl(String bucketName, String filePath, int expirySeconds) {
        try {
            if (!fileExists(bucketName, filePath)) {
                logger.warn("文件不存在，无法生成URL: bucket={}, path={}", bucketName, filePath);
                throw new RuntimeException("文件不存在");
            }
            return minioUtils.getPresignedUrl(bucketName, filePath, expirySeconds);
        } catch (Exception e) {
            logger.error("生成文件URL失败: bucket={}, path={}", bucketName, filePath, e);
            throw new RuntimeException("生成文件URL失败", e);
        }
    }

    @Override
    public List<String> listBuckets() {
        try {
            List<Bucket> buckets = minioUtils.listBuckets();
            return buckets.stream().map(Bucket::name).collect(Collectors.toList());
        } catch (Exception e) {
            logger.error("获取存储桶列表失败", e);
            throw new RuntimeException("获取存储桶列表失败", e);
        }
    }

    @Override
    public boolean bucketExists(String bucketName) {
        try {
            return minioUtils.bucketExists(bucketName);
        } catch (Exception e) {
            logger.error("检查存储桶存在失败: bucket={}", bucketName, e);
            throw new RuntimeException("检查存储桶存在失败", e);
        }
    }

    @Override
    public void createBucket(String bucketName) {
        try {
            if (!bucketExists(bucketName)) {
                minioUtils.makeBucket(bucketName);
                logger.info("创建存储桶成功: bucket={}", bucketName);
            } else {
                logger.info("存储桶已存在: bucket={}", bucketName);
            }
        } catch (Exception e) {
            logger.error("创建存储桶失败: bucket={}", bucketName, e);
            throw new RuntimeException("创建存储桶失败", e);
        }
    }

    @Override
    public void deleteBucket(String bucketName) {
        try {
            if (bucketExists(bucketName)) {
                // 检查存储桶是否为空
                Iterable<Result<Item>> results = minioUtils.listObjects(bucketName);
                boolean isEmpty = !results.iterator().hasNext();

                if (isEmpty) {
                    minioUtils.removeBucket(bucketName);
                    logger.info("删除存储桶成功: bucket={}", bucketName);
                } else {
                    logger.warn("无法删除非空存储桶: bucket={}", bucketName);
                    throw new RuntimeException("无法删除非空存储桶");
                }
            } else {
                logger.info("存储桶不存在，无需删除: bucket={}", bucketName);
            }
        } catch (Exception e) {
            logger.error("删除存储桶失败: bucket={}", bucketName, e);
            throw new RuntimeException("删除存储桶失败", e);
        }
    }

    /**
     * 确保存储桶存在，如果不存在则创建
     */
    private void ensureBucketExists(String bucketName) {
        try {
            if (!minioUtils.bucketExists(bucketName)) {
                minioUtils.makeBucket(bucketName);
                logger.info("自动创建存储桶: {}", bucketName);
            }
        } catch (Exception e) {
            logger.error("确保存储桶存在失败: bucket={}", bucketName, e);
            throw new RuntimeException("初始化存储桶失败", e);
        }
    }
}
