package com.emoon.tongue.service.impl;

import com.emoon.common.core.utils.StringUtils;
import com.emoon.tongue.service.MinioService;
import io.minio.*;
import io.minio.http.Method;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;

/**
 * MinIO服务实现类
 *
 * @author destiny
 * @date 2025-12-11
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MinioServiceImpl implements MinioService {

    private final MinioClient minioClient;

    @Value("${minio.bucket-name}")
    private String minioBucketName;

    @Value("${minio.endpoint}")
    private String minioEndpoint;

    @Value("${minio.public-endpoint}")
    private String minioPublicEndpoint;

    @Value("${minio.expiry-enabled:true}")
    private Boolean expiryEnabled;

    @Value("${minio.expiry-minutes:60}")
    private Integer expiryMinutes;


    @Override
    public String uploadFile(MultipartFile file) {
        // 生成唯一文件名
        String originalFilename = file.getOriginalFilename();
        String extension = originalFilename != null && originalFilename.contains(".")
            ? originalFilename.substring(originalFilename.lastIndexOf("."))
            : "";

        String objectName = generateObjectName(extension);
        return uploadFile(file, objectName);
    }

    @Override
    public String uploadFile(MultipartFile file, String objectName) {
        try {
            // 检查bucket是否存在，不存在则创建
            boolean bucketExists = minioClient.bucketExists(
                BucketExistsArgs.builder()
                    .bucket(minioBucketName)
                    .build()
            );

            if (!bucketExists) {
                minioClient.makeBucket(
                    MakeBucketArgs.builder()
                        .bucket(minioBucketName)
                        .build()
                );
                log.info("创建MinIO存储桶: {}", minioBucketName);
            }

            // 上传文件
            minioClient.putObject(
                PutObjectArgs.builder()
                    .bucket(minioBucketName)
                    .object(objectName)
                    .stream(file.getInputStream(), file.getSize(), -1)
                    .contentType(file.getContentType())
                    .build()
            );

            // 生成访问URL
            return getFileUrl(objectName);

        } catch (Exception e) {
            log.error("文件上传失败: {}", e.getMessage(), e);
            throw new RuntimeException("文件上传失败: " + e.getMessage());
        }
    }

    @Override
    public boolean deleteFile(String objectName) {
        try {
            minioClient.removeObject(
                RemoveObjectArgs.builder()
                    .bucket(minioBucketName)
                    .object(objectName)
                    .build()
            );
            log.info("删除文件成功: {}", objectName);
            return true;
        } catch (Exception e) {
            log.error("删除文件失败: {}", e.getMessage(), e);
            return false;
        }
    }

    /**
     * 生成文件对象名
     *
     * @param extension 文件扩展名
     * @return 文件对象名
     */
    private String generateObjectName(String extension) {
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String random = String.valueOf(System.currentTimeMillis() % 10000);
        return "tongue-images/" + timestamp + "_" + random + extension;
    }

    /**
     * 获取文件访问URL
     *
     * @param objectName 文件对象名
     * @return 访问URL
     */
    private String getFileUrl(String objectName) {
        try {
            // 如果未启用超时，直接返回公网endpoint的URL（不生成预签名URL）
            if (Boolean.FALSE.equals(expiryEnabled)) {
                // 如果是localhost，直接返回endpoint路径
                if (StringUtils.equals(minioEndpoint, "localhost")) {
                    return minioEndpoint + "/" + minioBucketName + "/" + objectName;
                }
                // 直接返回公网endpoint的URL
                return minioPublicEndpoint + "/" + minioBucketName + "/" + objectName;
            }

            // 生成预签名URL，使用配置的超时时间
            String url = minioClient.getPresignedObjectUrl(
                GetPresignedObjectUrlArgs.builder()
                    .method(Method.GET)
                    .bucket(minioBucketName)
                    .object(objectName)
                    .expiry(expiryMinutes, TimeUnit.MINUTES)
                    .build()
            );

            // 如果是localhost，直接返回endpoint路径
            if (StringUtils.equals(minioEndpoint, "localhost")) {
                return minioEndpoint + "/" + minioBucketName + "/" + objectName;
            }

            // 将内网endpoint替换为公网endpoint
            String publicUrl = url.replace(minioEndpoint, minioPublicEndpoint);

            return publicUrl;
        } catch (Exception e) {
            log.error("获取文件URL失败: {}", e.getMessage(), e);
            // 返回直接构造的URL作为fallback，使用公网endpoint
            return minioPublicEndpoint + "/" + minioBucketName + "/" + objectName;
        }
    }
}
