package com.dora.controller;

import com.dora.common.Result;
import com.dora.dto.OssPresignedUrlRequest;
import com.dora.service.OssPostSignatureService;
import com.dora.service.OssService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import jakarta.validation.Valid;
import java.util.Map;
import com.dora.util.OssUtil;

@RestController
@RequestMapping("/user/oss")
@RequiredArgsConstructor
@Slf4j
@Tag(name = "OSS文件上传", description = "阿里云OSS上传相关接口")
public class OssController {

    private final OssService ossService;
    private final OssPostSignatureService ossPostSignatureService;

    @PostMapping("/presigned-url")
    @Operation(summary = "生成预签名上传URL (POST)", description = "使用JSON请求体生成预签名上传URL")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "成功生成预签名URL",
                    content = @Content(schema = @Schema(implementation = Map.class))),
            @ApiResponse(responseCode = "400", description = "请求参数错误"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    public Result<Map<String, Object>> generatePresignedUrlPost(
            @Valid @RequestBody OssPresignedUrlRequest request) {
        try {
            Map<String, Object> result = ossService.generatePresignedUploadUrl(request.getFileName(), request.getUserId());
            return Result.success(result, "预签名URL生成成功");
        } catch (Exception e) {
            log.error("Failed to generate presigned URL: {}", e.getMessage(), e);
            return Result.error(500, "生成预签名URL失败: " + e.getMessage());
        }
    }

    @GetMapping("/presigned-url")
    @Operation(summary = "生成预签名上传URL (GET)", description = "使用查询参数生成预签名上传URL")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "成功生成预签名URL",
                    content = @Content(schema = @Schema(implementation = Map.class))),
            @ApiResponse(responseCode = "400", description = "请求参数错误"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    public Result<Map<String, Object>> generatePresignedUrlGet(
            @Parameter(description = "文件名", required = true) @RequestParam String fileName,
            @Parameter(description = "用户ID", required = true) @RequestParam String userId,
            @Parameter(description = "文件类型", required = false) @RequestParam(required = false) String fileType,
            @Parameter(description = "文件大小", required = false) @RequestParam(required = false) Long fileSize) {
        try {
            // 验证文件类型
            if (fileType != null && !fileType.startsWith("image/")) {
                return Result.error(400, "不支持的文件类型，仅支持图片格式");
            }
            
            // 验证文件大小
            if (fileSize != null && fileSize > 100 * 1024 * 1024) {
                return Result.error(400, "文件大小不能超过100MB");
            }
            
            Map<String, Object> result = ossService.generatePresignedUploadUrl(fileName, userId);
            return Result.success(result, "预签名URL生成成功");
        } catch (Exception e) {
            log.error("Failed to generate presigned URL: {}", e.getMessage(), e);
            return Result.error(500, "生成预签名URL失败: " + e.getMessage());
        }
    }

    @PostMapping("/post-signature")
    @Operation(summary = "生成OSS POST签名", description = "生成OSS POST签名版本4，用于前端直接上传文件")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "成功生成POST签名",
                    content = @Content(schema = @Schema(implementation = Map.class))),
            @ApiResponse(responseCode = "400", description = "请求参数错误"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    public Result<Map<String, Object>> generatePostSignature(
            @Parameter(description = "请求参数") @RequestBody Map<String, Object> requestBody) {
        try {
            // 从请求体获取参数
            String fileName = (String) requestBody.get("fileName");
            Object userIdObj = requestBody.get("userId");
            String userId = null;
            
            if (userIdObj != null) {
                userId = userIdObj.toString();
            }
            
            // 参数验证
            if (fileName == null || fileName.trim().isEmpty()) {
                return Result.error(400, "文件名不能为空");
            }
            if (userId == null) {
                return Result.error(400, "用户ID不能为空");
            }
            
            // 验证文件类型
            if (!OssUtil.isAllowedFileType(fileName)) {
                return Result.error(400, "不支持的文件类型，支持格式：图片(jpg,jpeg,png,gif,bmp,webp)、压缩包(zip,rar,7z,tar,gz,bz2,xz)、文档(pdf,txt,md,json,xml,csv)");
            }
            
            Map<String, Object> result = ossPostSignatureService.getPostSignatureForOssUpload(userId, fileName);
            return Result.success(result, "POST签名生成成功");
        } catch (Exception e) {
            log.error("Failed to generate POST signature: {}", e.getMessage(), e);
            return Result.error(500, "生成POST签名失败: " + e.getMessage());
        }
    }

    @PostMapping("/post-signature/json")
    @Operation(summary = "生成OSS POST签名 (JSON)", description = "使用JSON请求体生成OSS POST签名版本4")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "成功生成POST签名",
                    content = @Content(schema = @Schema(implementation = Map.class))),
            @ApiResponse(responseCode = "400", description = "请求参数错误"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    public Result<Map<String, Object>> generatePostSignatureJson(
            @Valid @RequestBody OssPresignedUrlRequest request) {
        try {
            // 验证文件类型
            if (!OssUtil.isAllowedFileType(request.getFileName())) {
                return Result.error(400, "不支持的文件类型，支持格式：图片(jpg,jpeg,png,gif,bmp,webp)、压缩包(zip,rar,7z,tar,gz,bz2,xz)、文档(pdf,txt,md,json,xml,csv)");
            }
            
            Map<String, Object> result = ossPostSignatureService.getPostSignatureForOssUpload(request.getUserId(), request.getFileName());
            return Result.success(result, "POST签名生成成功");
        } catch (Exception e) {
            log.error("Failed to generate POST signature: {}", e.getMessage(), e);
            return Result.error(500, "生成POST签名失败: " + e.getMessage());
        }
    }

    @PostMapping("/callback")
    @Operation(summary = "OSS上传回调", description = "处理OSS文件上传完成后的回调通知")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "回调处理成功",
                    content = @Content(schema = @Schema(implementation = Map.class))),
            @ApiResponse(responseCode = "400", description = "回调数据错误"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    public Result<Map<String, Object>> handleCallback(
            @Parameter(description = "回调数据") @RequestBody Map<String, String> callbackData) {
        try {
            Map<String, Object> result = ossService.handleCallback(callbackData);
            return Result.success(result, "回调处理成功");
        } catch (Exception e) {
            log.error("Failed to handle callback: {}", e.getMessage(), e);
            return Result.error(500, "回调处理失败: " + e.getMessage());
        }
    }

    @DeleteMapping("/file")
    @Operation(summary = "删除OSS文件", description = "删除指定的OSS文件")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "文件删除成功"),
            @ApiResponse(responseCode = "400", description = "请求参数错误"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    public Result<String> deleteFile(
            @Parameter(description = "对象键", required = true) @RequestParam String objectKey) {
        try {
            boolean success = ossService.deleteFile(objectKey);
            if (success) {
                return Result.success("文件删除成功");
            } else {
                return Result.error(400, "文件删除失败");
            }
        } catch (Exception e) {
            log.error("Failed to delete file: {}", e.getMessage(), e);
            return Result.error(500, "删除文件失败: " + e.getMessage());
        }
    }
} 