package com.rj.utils;

import com.rj.service.MinIOService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

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

/**
 * MinIO 临时访问URL生成工具类
 * 提供各种场景下的临时URL生成方法
 * 
 * @author rj
 * @date 2025-10-02
 */
@Slf4j
@Component
public class MinIOUrlGenerator {

    @Autowired
    private MinIOService minioService;

    /**
     * 生成临时访问URL（1小时有效）
     * 
     * @param fileName 文件名
     * @return 临时访问URL信息
     */
    public UrlInfo generateTempUrl(String fileName) {
        return generateTempUrl(fileName, 3600); // 1小时
    }

    /**
     * 生成临时访问URL（指定过期时间）
     * 
     * @param fileName 文件名
     * @param expiresInSeconds 过期时间（秒）
     * @return 临时访问URL信息
     */
    public UrlInfo generateTempUrl(String fileName, int expiresInSeconds) {
        try {
            String presignedUrl = minioService.getPresignedUrl(fileName, expiresInSeconds);
            
            if (presignedUrl != null) {
                UrlInfo urlInfo = new UrlInfo();
                urlInfo.setFileName(fileName);
                urlInfo.setUrl(presignedUrl);
                urlInfo.setExpiresInSeconds(expiresInSeconds);
                urlInfo.setGeneratedAt(LocalDateTime.now());
                urlInfo.setExpiresAt(LocalDateTime.now().plusSeconds(expiresInSeconds));
                urlInfo.setSuccess(true);
                
                log.info("生成临时访问URL成功: 文件={}, 有效期={}秒,链接是= {}", fileName, expiresInSeconds,presignedUrl);
                return urlInfo;
            } else {
                return createErrorUrlInfo(fileName, "生成预签名URL失败");
            }
        } catch (Exception e) {
            log.error("生成临时访问URL失败: 文件={}, 错误={}", fileName, e.getMessage());
            return createErrorUrlInfo(fileName, "生成临时访问URL异常: " + e.getMessage());
        }
    }

    /**
     * 生成临时访问URL（指定存储桶）
     * 
     * @param bucketName 存储桶名称
     * @param fileName 文件名
     * @param expiresInSeconds 过期时间（秒）
     * @return 临时访问URL信息
     */
    public UrlInfo generateTempUrl(String bucketName, String fileName, int expiresInSeconds) {
        try {
            // 检查文件是否存在
            if (!minioService.fileExists(bucketName, fileName)) {
                return createErrorUrlInfo(fileName, "文件不存在");
            }

            String presignedUrl = minioService.getPresignedUrl(fileName, expiresInSeconds);
            
            if (presignedUrl != null) {
                UrlInfo urlInfo = new UrlInfo();
                urlInfo.setBucketName(bucketName);
                urlInfo.setFileName(fileName);
                urlInfo.setUrl(presignedUrl);
                urlInfo.setExpiresInSeconds(expiresInSeconds);
                urlInfo.setGeneratedAt(LocalDateTime.now());
                urlInfo.setExpiresAt(LocalDateTime.now().plusSeconds(expiresInSeconds));
                urlInfo.setSuccess(true);
                
                log.info("生成临时访问URL成功: 存储桶={}, 文件={}, 有效期={}秒", bucketName, fileName, expiresInSeconds);
                return urlInfo;
            } else {
                return createErrorUrlInfo(fileName, "生成预签名URL失败");
            }
        } catch (Exception e) {
            log.error("生成临时访问URL失败: 存储桶={}, 文件={}, 错误={}", bucketName, fileName, e.getMessage());
            return createErrorUrlInfo(fileName, "生成临时访问URL异常: " + e.getMessage());
        }
    }

    /**
     * 批量生成临时访问URL
     * 
     * @param fileNames 文件名列表
     * @param expiresInSeconds 过期时间（秒）
     * @return 临时访问URL信息列表
     */
    public Map<String, UrlInfo> generateBatchTempUrls(String[] fileNames, int expiresInSeconds) {
        Map<String, UrlInfo> results = new HashMap<>();
        
        for (String fileName : fileNames) {
            UrlInfo urlInfo = generateTempUrl(fileName, expiresInSeconds);
            results.put(fileName, urlInfo);
        }
        
        log.info("批量生成临时访问URL完成: 文件数量={}, 有效期={}秒", fileNames.length, expiresInSeconds);
        return results;
    }

    /**
     * 生成短期临时URL（15分钟有效）
     * 适用于临时预览
     * 
     * @param fileName 文件名
     * @return 临时访问URL信息
     */
    public UrlInfo generateShortTermUrl(String fileName) {
        return generateTempUrl(fileName, 900); // 15分钟
    }

    /**
     * 生成中期临时URL（4小时有效）
     * 适用于文件分享
     * 
     * @param fileName 文件名
     * @return 临时访问URL信息
     */
    public UrlInfo generateMediumTermUrl(String fileName) {
        return generateTempUrl(fileName, 14400); // 4小时
    }

    /**
     * 生成长期临时URL（24小时有效）
     * 适用于下载链接
     * 
     * @param fileName 文件名
     * @return 临时访问URL信息
     */
    public UrlInfo generateLongTermUrl(String fileName) {
        return generateTempUrl(fileName, 86400); // 24小时
    }

    /**
     * 生成最长期临时URL（7天有效）
     * 适用于长期访问
     * 
     * @param fileName 文件名
     * @return 临时访问URL信息
     */
    public UrlInfo generateMaxTermUrl(String fileName) {
        return generateTempUrl(fileName, 604800); // 7天
    }

    /**
     * 根据时间单位生成临时URL
     * 
     * @param fileName 文件名
     * @param duration 持续时间
     * @param timeUnit 时间单位
     * @return 临时访问URL信息
     */
    public UrlInfo generateTempUrl(String fileName, long duration, TimeUnit timeUnit) {
        int expiresInSeconds = (int) timeUnit.toSeconds(duration);
        return generateTempUrl(fileName, expiresInSeconds);
    }

    /**
     * 创建错误的URL信息对象
     */
    private UrlInfo createErrorUrlInfo(String fileName, String errorMessage) {
        UrlInfo urlInfo = new UrlInfo();
        urlInfo.setFileName(fileName);
        urlInfo.setSuccess(false);
        urlInfo.setErrorMessage(errorMessage);
        urlInfo.setGeneratedAt(LocalDateTime.now());
        return urlInfo;
    }

    /**
     * URL信息类
     */
    public static class UrlInfo {
        private String bucketName;
        private String fileName;
        private String url;
        private int expiresInSeconds;
        private LocalDateTime generatedAt;
        private LocalDateTime expiresAt;
        private boolean success;
        private String errorMessage;

        // Getters and Setters
        public String getBucketName() {
            return bucketName;
        }

        public void setBucketName(String bucketName) {
            this.bucketName = bucketName;
        }

        public String getFileName() {
            return fileName;
        }

        public void setFileName(String fileName) {
            this.fileName = fileName;
        }

        public String getUrl() {
            return url;
        }

        public void setUrl(String url) {
            this.url = url;
        }

        public int getExpiresInSeconds() {
            return expiresInSeconds;
        }

        public void setExpiresInSeconds(int expiresInSeconds) {
            this.expiresInSeconds = expiresInSeconds;
        }

        public LocalDateTime getGeneratedAt() {
            return generatedAt;
        }

        public void setGeneratedAt(LocalDateTime generatedAt) {
            this.generatedAt = generatedAt;
        }

        public LocalDateTime getExpiresAt() {
            return expiresAt;
        }

        public void setExpiresAt(LocalDateTime expiresAt) {
            this.expiresAt = expiresAt;
        }

        public boolean isSuccess() {
            return success;
        }

        public void setSuccess(boolean success) {
            this.success = success;
        }

        public String getErrorMessage() {
            return errorMessage;
        }

        public void setErrorMessage(String errorMessage) {
            this.errorMessage = errorMessage;
        }

        /**
         * 获取格式化的过期时间字符串
         */
        public String getFormattedExpiresAt() {
            if (expiresAt != null) {
                return expiresAt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            }
            return null;
        }

        /**
         * 检查URL是否已过期
         */
        public boolean isExpired() {
            return expiresAt != null && LocalDateTime.now().isAfter(expiresAt);
        }

        /**
         * 获取剩余有效时间（秒）
         */
        public long getRemainingSeconds() {
            if (expiresAt != null) {
                return java.time.Duration.between(LocalDateTime.now(), expiresAt).getSeconds();
            }
            return 0;
        }

        @Override
        public String toString() {
            return "UrlInfo{" +
                    "bucketName='" + bucketName + '\'' +
                    ", fileName='" + fileName + '\'' +
                    ", url='" + url + '\'' +
                    ", expiresInSeconds=" + expiresInSeconds +
                    ", generatedAt=" + generatedAt +
                    ", expiresAt=" + expiresAt +
                    ", success=" + success +
                    ", errorMessage='" + errorMessage + '\'' +
                    '}';
        }
    }
}
