package com.changhu.support.minio.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.changhu.common.exception.MessageException;
import com.changhu.support.minio.MinioProperties;
import com.changhu.support.minio.service.MinioService;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * fileName: MinioServiceImpl
 * author: LuoZhun
 * createTime: 2023/11/10 17:36
 * description: some...
 */
@Slf4j
@Service
public class MinioServiceImpl implements MinioService {

    @Autowired
    private MinioProperties minioProperties;

    @Autowired
    private MinioClient minioClient;

    @Override
    public boolean bucketExists(String bucketName) {
        try {
            return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    @Override
    public boolean createBucket(String bucketName) {
        try {
            minioClient.makeBucket(MakeBucketArgs.builder()
                    .bucket(bucketName).build());
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
        return true;
    }

    @Override
    public boolean removeBucket(String bucketName) {
        try {
            minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
        return true;
    }

    @Override
    public List<Bucket> getAllBuckets() {
        try {
            return minioClient.listBuckets();
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    @Override
    public String upload(MultipartFile file) {
        return upload(file, "");
    }

    @Override
    public String upload(MultipartFile file, String baseDir) {
        String originalFilename = file.getOriginalFilename();
        if (StrUtil.isBlank(originalFilename)) {
            return null;
        }
        try {
            PutObjectArgs objectArgs = PutObjectArgs.builder()
                    .bucket(minioProperties.getBucketName())
                    .object(baseDir + LocalDateTime.now().format(DateTimeFormatter.ofPattern("/yyyy/MM/dd/"))
                            + IdUtil.simpleUUID()
                            + originalFilename.substring(originalFilename.lastIndexOf(".")))
                    .stream(file.getInputStream(), file.getSize(), -1)
                    .contentType(file.getContentType())
                    .build();
            ObjectWriteResponse objectWriteResponse = minioClient.putObject(objectArgs);
            String objectPath = StrUtil.startWith(objectWriteResponse.object(), "/") ? objectWriteResponse.object() : "/" + objectWriteResponse.object();
            return "/" + objectWriteResponse.bucket() + objectPath;
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    @Override
    public String upload(File file, String baseDir) {
        String fileName = file.getName();
        if (StrUtil.isBlank(fileName)) {
            return null;
        }
        try {
            PutObjectArgs objectArgs = PutObjectArgs.builder()
                    .bucket(minioProperties.getBucketName())
                    .object(baseDir + LocalDateTime.now().format(DateTimeFormatter.ofPattern("/yyyy/MM/dd/"))
                            + IdUtil.simpleUUID()
                            + fileName.substring(fileName.lastIndexOf(".")))
                    .stream(new FileInputStream(file), file.length(), -1)
                    .build();
            ObjectWriteResponse objectWriteResponse = minioClient.putObject(objectArgs);
            String objectPath = StrUtil.startWith(objectWriteResponse.object(), "/") ? objectWriteResponse.object() : "/" + objectWriteResponse.object();
            return "/" + objectWriteResponse.bucket() + objectPath;
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    @Override
    public void removeFile(String path) {
        try {
            //找出第二个/的位置
            int index = path.indexOf('/', 1);
            minioClient.removeObject(RemoveObjectArgs.builder()
                    //第一个/与第二个/之间的是bucketName
                    .bucket(path.substring(1, index))
                    //第二个/之后的path是objectName
                    .object(path.substring(index))
                    .build());
        } catch (Exception e) {
            log.error("文件删除失败:{}", e.getMessage());
        }
    }

    @Override
    public void removeFiles(Set<String> paths) {
        paths.forEach(this::removeFile);
    }

    @Override
    public String preview(String fileName) {
        GetPresignedObjectUrlArgs build = GetPresignedObjectUrlArgs.builder()
                .bucket(minioProperties.getBucketName())
                .object(fileName)
                .method(Method.GET)
                .build();
        try {
            return minioClient.getPresignedObjectUrl(build);
        } catch (Exception e) {
            log.error("minio预览异常:{}", e.getMessage());
        }
        return null;
    }

    @Override
    public void download(String fileName, HttpServletResponse res) {

    }

    @Override
    public String getResignedObjectUrl(String bucketName, String objectName) {
        try {
            return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                    .method(Method.PUT)
                    .bucket(bucketName)
                    .object(objectName)
                    .expiry(10, TimeUnit.SECONDS)
                    .build());
        } catch (Exception e) {
            throw new MessageException("获取临时上传地址失败:{}", e.getMessage());
        }
    }
}
