package com.rj.controller;

import com.rj.service.ITtsRequestLogService;
import com.rj.service.MinIOService;
import com.rj.utils.MinIOUtil;
import com.rj.utils.MinIOUrlGenerator;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * MinIO 文件管理控制器
 * 
 * @author rj
 * @date 2025-10-02
 */
@Slf4j
@RestController
@RequestMapping("/api/minio")
@Tag(name = "MinIO文件管理", description = "MinIO对象存储文件管理接口")
public class MinIOController {

    @Autowired
    private MinIOService minioService;

    @Autowired
    private MinIOUrlGenerator urlGenerator;

    @PostMapping("/upload")
    @Operation(summary = "上传文件", description = "上传文件到MinIO存储")
    public ResponseEntity<Map<String, Object>> uploadFile(
            @Parameter(description = "上传的文件") @RequestParam("file") MultipartFile file) {
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            if (file.isEmpty()) {
                result.put("success", false);
                result.put("message", "文件不能为空");
                return ResponseEntity.badRequest().body(result);
            }

            String fileUrl = minioService.uploadFile(file);
            
            result.put("success", true);
            result.put("message", "文件上传成功");
            result.put("fileName", file.getOriginalFilename());
            result.put("fileSize", file.getSize());
            result.put("fileUrl", fileUrl);
            
            log.info("文件上传成功: {}, 大小: {} bytes", file.getOriginalFilename(), file.getSize());
            
            return ResponseEntity.ok(result);
            
        } catch (Exception e) {
            log.error("文件上传失败: {}", e.getMessage());
            result.put("success", false);
            result.put("message", "文件上传失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    @PostMapping("/upload/{bucketName}")
    @Operation(summary = "上传文件到指定存储桶", description = "上传文件到指定的MinIO存储桶")
    public ResponseEntity<Map<String, Object>> uploadFileToBucket(
            @Parameter(description = "存储桶名称") @PathVariable String bucketName,
            @Parameter(description = "上传的文件") @RequestParam("file") MultipartFile file) {
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            if (file.isEmpty()) {
                result.put("success", false);
                result.put("message", "文件不能为空");
                return ResponseEntity.badRequest().body(result);
            }

            String fileUrl = minioService.uploadFile(file, bucketName);
            
            result.put("success", true);
            result.put("message", "文件上传成功");
            result.put("bucketName", bucketName);
            result.put("fileName", file.getOriginalFilename());
            result.put("fileSize", file.getSize());
            result.put("fileUrl", fileUrl);
            
            log.info("文件上传成功到存储桶 {}: {}, 大小: {} bytes", bucketName, file.getOriginalFilename(), file.getSize());
            
            return ResponseEntity.ok(result);
            
        } catch (Exception e) {
            log.error("文件上传失败: {}", e.getMessage());
            result.put("success", false);
            result.put("message", "文件上传失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    @GetMapping("/download/{fileName}")
    @Operation(summary = "下载文件", description = "从MinIO下载文件")
    public ResponseEntity<InputStreamResource> downloadFile(
            @Parameter(description = "文件名") @PathVariable String fileName) {
        
        try {
            InputStream inputStream = minioService.downloadFile(fileName);
            
            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8);
            
            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + encodedFileName + "\"")
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .body(new InputStreamResource(inputStream));
                    
        } catch (Exception e) {
            log.error("文件下载失败: {}", e.getMessage());
            return ResponseEntity.notFound().build();
        }
    }

    @GetMapping("/download/{bucketName}/{fileName}")
    @Operation(summary = "从指定存储桶下载文件", description = "从指定MinIO存储桶下载文件")
    public ResponseEntity<InputStreamResource> downloadFileFromBucket(
            @Parameter(description = "存储桶名称") @PathVariable String bucketName,
            @Parameter(description = "文件名") @PathVariable String fileName) {
        
        try {
            InputStream inputStream = minioService.downloadFile(bucketName, fileName);
            
            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8);
            
            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + encodedFileName + "\"")
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .body(new InputStreamResource(inputStream));
                    
        } catch (Exception e) {
            log.error("文件下载失败: {}", e.getMessage());
            return ResponseEntity.notFound().build();
        }
    }

    @DeleteMapping("/delete/{fileName}")
    @Operation(summary = "删除文件", description = "从MinIO删除文件")
    public ResponseEntity<Map<String, Object>> deleteFile(
            @Parameter(description = "文件名") @PathVariable String fileName) {
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            boolean success = minioService.deleteFile(fileName);
            
            if (success) {
                result.put("success", true);
                result.put("message", "文件删除成功");
                log.info("文件删除成功: {}", fileName);
                return ResponseEntity.ok(result);
            } else {
                result.put("success", false);
                result.put("message", "文件删除失败");
                return ResponseEntity.internalServerError().body(result);
            }
            
        } catch (Exception e) {
            log.error("文件删除失败: {}", e.getMessage());
            result.put("success", false);
            result.put("message", "文件删除失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    @GetMapping("/list")
    @Operation(summary = "获取文件列表", description = "获取默认存储桶中的文件列表")
    public ResponseEntity<Map<String, Object>> listFiles() {
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            List<String> files = minioService.listFiles();
            
            result.put("success", true);
            result.put("message", "获取文件列表成功");
            result.put("files", files);
            result.put("count", files.size());
            
            return ResponseEntity.ok(result);
            
        } catch (Exception e) {
            log.error("获取文件列表失败: {}", e.getMessage());
            result.put("success", false);
            result.put("message", "获取文件列表失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    @GetMapping("/list/{bucketName}")
    @Operation(summary = "获取指定存储桶文件列表", description = "获取指定存储桶中的文件列表")
    public ResponseEntity<Map<String, Object>> listFilesInBucket(
            @Parameter(description = "存储桶名称") @PathVariable String bucketName) {
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            List<String> files = minioService.listFiles(bucketName);
            
            result.put("success", true);
            result.put("message", "获取文件列表成功");
            result.put("bucketName", bucketName);
            result.put("files", files);
            result.put("count", files.size());
            
            return ResponseEntity.ok(result);
            
        } catch (Exception e) {
            log.error("获取文件列表失败: {}", e.getMessage());
            result.put("success", false);
            result.put("message", "获取文件列表失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    @GetMapping("/list-details")
    @Operation(summary = "获取文件详细信息列表", description = "获取默认存储桶中文件的详细信息列表")
    public ResponseEntity<Map<String, Object>> listFileDetails() {
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            List<MinIOUtil.FileInfo> files = minioService.listFileDetails();
            
            result.put("success", true);
            result.put("message", "获取文件详细信息成功");
            result.put("files", files);
            result.put("count", files.size());
            
            return ResponseEntity.ok(result);
            
        } catch (Exception e) {
            log.error("获取文件详细信息失败: {}", e.getMessage());
            result.put("success", false);
            result.put("message", "获取文件详细信息失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    @GetMapping("/presigned-url/{fileName}")
    @Operation(summary = "获取文件预签名URL", description = "获取文件的临时访问URL")
    public ResponseEntity<Map<String, Object>> getPresignedUrl(
            @Parameter(description = "文件名") @PathVariable String fileName,
            @Parameter(description = "过期时间（秒），默认7天") @RequestParam(defaultValue = "604800") int expires) {
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            String presignedUrl = minioService.getPresignedUrl(fileName, expires);
            
            if (presignedUrl != null) {
                result.put("success", true);
                result.put("message", "获取预签名URL成功");
                result.put("fileName", fileName);
                result.put("presignedUrl", presignedUrl);
                result.put("expires", expires);
                return ResponseEntity.ok(result);
            } else {
                result.put("success", false);
                result.put("message", "获取预签名URL失败");
                return ResponseEntity.internalServerError().body(result);
            }
            
        } catch (Exception e) {
            log.error("获取预签名URL失败: {}", e.getMessage());
            result.put("success", false);
            result.put("message", "获取预签名URL失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    @GetMapping("/buckets")
    @Operation(summary = "获取所有存储桶", description = "获取MinIO中所有存储桶列表")
    public ResponseEntity<Map<String, Object>> getAllBuckets() {
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            List<String> buckets = minioService.getAllBuckets();
            
            result.put("success", true);
            result.put("message", "获取存储桶列表成功");
            result.put("buckets", buckets);
            result.put("count", buckets.size());
            
            return ResponseEntity.ok(result);
            
        } catch (Exception e) {
            log.error("获取存储桶列表失败: {}", e.getMessage());
            result.put("success", false);
            result.put("message", "获取存储桶列表失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    @PostMapping("/bucket/{bucketName}")
    @Operation(summary = "创建存储桶", description = "创建新的MinIO存储桶")
    public ResponseEntity<Map<String, Object>> createBucket(
            @Parameter(description = "存储桶名称") @PathVariable String bucketName) {
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            boolean success = minioService.createBucket(bucketName);
            
            if (success) {
                result.put("success", true);
                result.put("message", "存储桶创建成功");
                result.put("bucketName", bucketName);
                log.info("存储桶创建成功: {}", bucketName);
                return ResponseEntity.ok(result);
            } else {
                result.put("success", false);
                result.put("message", "存储桶创建失败");
                return ResponseEntity.internalServerError().body(result);
            }
            
        } catch (Exception e) {
            log.error("存储桶创建失败: {}", e.getMessage());
            result.put("success", false);
            result.put("message", "存储桶创建失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    // ==================== 临时访问URL生成接口 ====================

    @GetMapping("/temp-url/{fileName}")
    @Operation(summary = "生成临时访问URL", description = "为指定文件生成临时访问URL（默认1小时有效）")
    public ResponseEntity<Map<String, Object>> generateTempUrl(
            @Parameter(description = "文件名") @PathVariable String fileName) {
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            MinIOUrlGenerator.UrlInfo urlInfo = urlGenerator.generateTempUrl(fileName);
            
            if (urlInfo.isSuccess()) {
                result.put("success", true);
                result.put("message", "临时访问URL生成成功");
                result.put("fileName", urlInfo.getFileName());
                result.put("tempUrl", urlInfo.getUrl());
                result.put("expiresInSeconds", urlInfo.getExpiresInSeconds());
                result.put("generatedAt", urlInfo.getGeneratedAt());
                result.put("expiresAt", urlInfo.getExpiresAt());
                result.put("formattedExpiresAt", urlInfo.getFormattedExpiresAt());
                
                log.info("临时访问URL生成成功: {}", fileName);
                return ResponseEntity.ok(result);
            } else {
                result.put("success", false);
                result.put("message", urlInfo.getErrorMessage());
                return ResponseEntity.badRequest().body(result);
            }
            
        } catch (Exception e) {
            log.error("生成临时访问URL失败: {}", e.getMessage());
            result.put("success", false);
            result.put("message", "生成临时访问URL失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }
    @Autowired
    ITtsRequestLogService ttsRequestLogService;
    @GetMapping("/temp-url/{fileName}/{expiresInSeconds}")
    @Operation(summary = "生成临时访问URL（指定过期时间）", description = "为指定文件生成临时访问URL，可指定过期时间")
    public ResponseEntity<Map<String, Object>> generateTempUrlWithExpires(
            @Parameter(description = "文件名") @PathVariable String fileName,
            @Parameter(description = "过期时间（秒）") @PathVariable int expiresInSeconds) {
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 验证过期时间范围（1分钟到7天）
            if (expiresInSeconds < 60 || expiresInSeconds > 604800) {
                result.put("success", false);
                result.put("message", "过期时间必须在60秒到604800秒（7天）之间");
                return ResponseEntity.badRequest().body(result);
            }

            MinIOUrlGenerator.UrlInfo urlInfo = urlGenerator.generateTempUrl(fileName, expiresInSeconds);
            ttsRequestLogService.setShortUrlByAudioName(urlInfo);
            if (urlInfo.isSuccess()) {
                result.put("success", true);
                result.put("message", "临时访问URL生成成功");
                result.put("fileName", urlInfo.getFileName());
                result.put("tempUrl", urlInfo.getUrl());
                result.put("expiresInSeconds", urlInfo.getExpiresInSeconds());
                result.put("generatedAt", urlInfo.getGeneratedAt());
                result.put("expiresAt", urlInfo.getExpiresAt());
                result.put("formattedExpiresAt", urlInfo.getFormattedExpiresAt());
                
                log.info("临时访问URL生成成功: {}, 有效期: {}秒", fileName, expiresInSeconds);
                return ResponseEntity.ok(result);
            } else {
                result.put("success", false);
                result.put("message", urlInfo.getErrorMessage());
                return ResponseEntity.badRequest().body(result);
            }
            
        } catch (Exception e) {
            log.error("生成临时访问URL失败: {}", e.getMessage());
            result.put("success", false);
            result.put("message", "生成临时访问URL失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    @GetMapping("/temp-url/short/{fileName}")
    @Operation(summary = "生成短期临时URL", description = "生成15分钟有效的临时访问URL，适用于临时预览")
    public ResponseEntity<Map<String, Object>> generateShortTermUrl(
            @Parameter(description = "文件名") @PathVariable String fileName) {
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            MinIOUrlGenerator.UrlInfo urlInfo = urlGenerator.generateShortTermUrl(fileName);
            
            if (urlInfo.isSuccess()) {
                result.put("success", true);
                result.put("message", "短期临时访问URL生成成功（15分钟有效）");
                result.put("fileName", urlInfo.getFileName());
                result.put("tempUrl", urlInfo.getUrl());
                result.put("expiresInSeconds", urlInfo.getExpiresInSeconds());
                result.put("generatedAt", urlInfo.getGeneratedAt());
                result.put("expiresAt", urlInfo.getExpiresAt());
                result.put("formattedExpiresAt", urlInfo.getFormattedExpiresAt());
                
                return ResponseEntity.ok(result);
            } else {
                result.put("success", false);
                result.put("message", urlInfo.getErrorMessage());
                return ResponseEntity.badRequest().body(result);
            }
            
        } catch (Exception e) {
            log.error("生成短期临时访问URL失败: {}", e.getMessage());
            result.put("success", false);
            result.put("message", "生成短期临时访问URL失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    @GetMapping("/temp-url/long/{fileName}")
    @Operation(summary = "生成长期临时URL", description = "生成24小时有效的临时访问URL，适用于下载链接")
    public ResponseEntity<Map<String, Object>> generateLongTermUrl(
            @Parameter(description = "文件名") @PathVariable String fileName) {
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            MinIOUrlGenerator.UrlInfo urlInfo = urlGenerator.generateLongTermUrl(fileName);
            
            if (urlInfo.isSuccess()) {
                result.put("success", true);
                result.put("message", "长期临时访问URL生成成功（24小时有效）");
                result.put("fileName", urlInfo.getFileName());
                result.put("tempUrl", urlInfo.getUrl());
                result.put("expiresInSeconds", urlInfo.getExpiresInSeconds());
                result.put("generatedAt", urlInfo.getGeneratedAt());
                result.put("expiresAt", urlInfo.getExpiresAt());
                result.put("formattedExpiresAt", urlInfo.getFormattedExpiresAt());
                
                return ResponseEntity.ok(result);
            } else {
                result.put("success", false);
                result.put("message", urlInfo.getErrorMessage());
                return ResponseEntity.badRequest().body(result);
            }
            
        } catch (Exception e) {
            log.error("生成长期临时访问URL失败: {}", e.getMessage());
            result.put("success", false);
            result.put("message", "生成长期临时访问URL失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    @PostMapping("/temp-url/batch")
    @Operation(summary = "批量生成临时访问URL", description = "为多个文件批量生成临时访问URL")
    public ResponseEntity<Map<String, Object>> generateBatchTempUrls(
            @Parameter(description = "文件名列表") @RequestBody String[] fileNames,
            @Parameter(description = "过期时间（秒），默认1小时") @RequestParam(defaultValue = "3600") int expiresInSeconds) {
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            if (fileNames == null || fileNames.length == 0) {
                result.put("success", false);
                result.put("message", "文件名列表不能为空");
                return ResponseEntity.badRequest().body(result);
            }

            if (fileNames.length > 50) {
                result.put("success", false);
                result.put("message", "批量处理文件数量不能超过50个");
                return ResponseEntity.badRequest().body(result);
            }

            Map<String, MinIOUrlGenerator.UrlInfo> urlInfos = urlGenerator.generateBatchTempUrls(fileNames, expiresInSeconds);
            
            result.put("success", true);
            result.put("message", "批量生成临时访问URL完成");
            result.put("totalCount", fileNames.length);
            result.put("results", urlInfos);
            
            // 统计成功和失败数量
            long successCount = urlInfos.values().stream().mapToLong(info -> info.isSuccess() ? 1 : 0).sum();
            long failureCount = fileNames.length - successCount;
            
            result.put("successCount", successCount);
            result.put("failureCount", failureCount);
            
            log.info("批量生成临时访问URL完成: 总数={}, 成功={}, 失败={}", fileNames.length, successCount, failureCount);
            
            return ResponseEntity.ok(result);
            
        } catch (Exception e) {
            log.error("批量生成临时访问URL失败: {}", e.getMessage());
            result.put("success", false);
            result.put("message", "批量生成临时访问URL失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    @GetMapping("/temp-url/check/{fileName}")
    @Operation(summary = "检查文件并生成临时URL", description = "检查文件是否存在，如果存在则生成临时访问URL")
    public ResponseEntity<Map<String, Object>> checkAndGenerateTempUrl(
            @Parameter(description = "文件名") @PathVariable String fileName,
            @Parameter(description = "过期时间（秒），默认1小时") @RequestParam(defaultValue = "3600") int expiresInSeconds) {
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 先检查文件是否存在
            boolean exists = minioService.fileExists(fileName);
            
            if (!exists) {
                result.put("success", false);
                result.put("message", "文件不存在: " + fileName);
                result.put("fileExists", false);
                return ResponseEntity.notFound().build();
            }

            MinIOUrlGenerator.UrlInfo urlInfo = urlGenerator.generateTempUrl(fileName, expiresInSeconds);
            
            if (urlInfo.isSuccess()) {
                result.put("success", true);
                result.put("message", "文件存在，临时访问URL生成成功");
                result.put("fileExists", true);
                result.put("fileName", urlInfo.getFileName());
                result.put("tempUrl", urlInfo.getUrl());
                result.put("expiresInSeconds", urlInfo.getExpiresInSeconds());
                result.put("generatedAt", urlInfo.getGeneratedAt());
                result.put("expiresAt", urlInfo.getExpiresAt());
                result.put("formattedExpiresAt", urlInfo.getFormattedExpiresAt());
                
                return ResponseEntity.ok(result);
            } else {
                result.put("success", false);
                result.put("message", urlInfo.getErrorMessage());
                result.put("fileExists", true);
                return ResponseEntity.internalServerError().body(result);
            }
            
        } catch (Exception e) {
            log.error("检查文件并生成临时访问URL失败: {}", e.getMessage());
            result.put("success", false);
            result.put("message", "检查文件并生成临时访问URL失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }
}
