/**
 * @ProjectName: 智慧评标-主观分助手
 * @Package: com.zhpb.gdyd_zhpb_zgf.controller
 * @ClassName: FileController
 * @Description: 文件管理控制器，提供文件上传、ZIP解压等RESTful API接口
 * @Author: 张志锋
 * @Date: 2025-10-31
 * @Version: 1.0
 * @Copyright: © 2025 智慧评标-主观分助手
 */
package com.zhpb.gdyd_zhpb_zgf.controller;

import com.zhpb.gdyd_zhpb_zgf.dto.FileUploadRequest;
import com.zhpb.gdyd_zhpb_zgf.dto.FileUploadResponse;
import com.zhpb.gdyd_zhpb_zgf.dto.ProjectFilesResponse;
import com.zhpb.gdyd_zhpb_zgf.entity.mysql.File;
import com.zhpb.gdyd_zhpb_zgf.entity.mysql.Project;
import com.zhpb.gdyd_zhpb_zgf.repository.mysql.FileDirectoryRepository;
import com.zhpb.gdyd_zhpb_zgf.repository.mysql.FileRepository;
import com.zhpb.gdyd_zhpb_zgf.repository.mysql.ProjectRepository;
import com.zhpb.gdyd_zhpb_zgf.service.FileService;
import com.zhpb.gdyd_zhpb_zgf.service.FilePreviewService;
import com.zhpb.gdyd_zhpb_zgf.utils.ApiAuthUtils;
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 org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.zhpb.gdyd_zhpb_zgf.service.UserLogService;

import jakarta.servlet.http.HttpServletRequest;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 文件管理控制器
 */
@RestController
@RequestMapping("/api/v1/files")
@Tag(name = "文件管理", description = "文件上传、下载、管理相关接口")
public class FileController {
    @Autowired
    private FileService fileService;

    @Autowired
    private FilePreviewService filePreviewService;

    @Autowired
    private FileRepository fileRepository;

    @Autowired
    private ProjectRepository projectRepository;

    @Autowired
    private ApiAuthUtils apiAuthUtils;

    @Autowired
    private FileDirectoryRepository fileDirectoryRepository;

    @Autowired
    private UserLogService userLogService;

    private static final Logger logger = LoggerFactory.getLogger(FileController.class);

    /**
     * 上传ZIP压缩包
     */
    @PostMapping(value = "/uploadzip", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @Operation(
            summary = "上传ZIP压缩包",
            description = "上传ZIP压缩包并自动解压，支持的文件格式：PDF、DOC、DOCX、TXT。请求体类型：multipart/form-data"
    )
    @io.swagger.v3.oas.annotations.parameters.RequestBody(
            description = "文件上传表单，使用multipart/form-data格式",
            required = true,
            content = @Content(
                    mediaType = MediaType.MULTIPART_FORM_DATA_VALUE
            )
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "200",
                    description = "上传成功",
                    content = @Content(
                            mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = FileUploadResponse.class)
                    )
            ),
            @ApiResponse(
                    responseCode = "422",
                    description = "验证错误",
                    content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)
            )
    })
    public ResponseEntity<Map<String, Object>> uploadZip(
            @Parameter(description = "项目ID", required = true, example = "project-001")
            @RequestParam("project_id") String projectId,
            @Parameter(description = "ZIP文件", required = true)
            @RequestParam("file") MultipartFile file,
            HttpServletRequest request) {

        Map<String, Object> response = new HashMap<>();

        try {
            // 验证文件
            if (file.isEmpty()) {
                response.put("code", 422);
                response.put("message", "文件不能为空");
                return ResponseEntity.status(422).body(response);
            }

            String originalFilename = file.getOriginalFilename();
            if (originalFilename == null || !originalFilename.toLowerCase().endsWith(".zip")) {
                response.put("code", 422);
                response.put("message", "文件必须是ZIP格式");
                return ResponseEntity.status(422).body(response);
            }

            // 验证项目ID
            if (projectId == null || projectId.trim().isEmpty()) {
                response.put("code", 422);
                response.put("message", "项目ID不能为空");
                return ResponseEntity.status(422).body(response);
            }

            // 上传并解压
            fileService.uploadAndExtractZip(projectId, file);

            // 获取项目文件信息（与查询API保持一致的格式）
            ProjectFilesResponse.ProjectFilesData data = fileService.getProjectFiles(projectId);

            response.put("code", 0);
            response.put("message", "文件上传成功，共解压" + data.getTotalFiles() + "个文件");
            response.put("data", data);

            // 记录用户操作日志
            // 从请求头中获取userId和userName
            String userId = request.getHeader("User-Id");
            String userName = request.getHeader("User-Name");
            if (userId != null && !userId.isEmpty()) {
                userLogService.logUserOperation(userId, userName, projectId, 
                    "UPLOAD_FILE", "上传ZIP文件: " + file.getOriginalFilename() + ", 解压文件数: " + data.getTotalFiles(), 
                    null, request);
            }

            return ResponseEntity.ok(response);

        } catch (IllegalArgumentException e) {
            response.put("code", 422);
            response.put("message", e.getMessage());
            return ResponseEntity.status(422).body(response);
        } catch (org.springframework.web.multipart.MaxUploadSizeExceededException e) {
            response.put("code", 413);
            response.put("message", "文件大小超过限制，最大允许上传500MB");
            response.put("error", "MaxUploadSizeExceeded");
            return ResponseEntity.status(413).body(response);
        } catch (IOException e) {
            response.put("code", 500);
            response.put("message", "文件处理失败: " + e.getMessage());
            return ResponseEntity.status(500).body(response);
        } catch (Exception e) {
            response.put("code", 500);
            response.put("message", "系统错误: " + e.getMessage());
            return ResponseEntity.status(500).body(response);
        }
    }

    /**
     * PDF文件预览
     */
    @GetMapping("/preview/pdf/{file_id}")
    @Operation(
            summary = "PDF文件预览",
            description = "在线预览PDF文件，返回PDF文件流"
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "200",
                    description = "预览成功",
                    content = @Content(mediaType = MediaType.APPLICATION_PDF_VALUE)
            ),
            @ApiResponse(
                    responseCode = "404",
                    description = "文件不存在",
                    content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)
            ),
            @ApiResponse(
                    responseCode = "422",
                    description = "验证错误",
                    content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)
            )
    })
    public ResponseEntity<StreamingResponseBody> previewPdf(
            @Parameter(description = "文件ID", required = true)
            @PathVariable("file_id") String fileId) {
        // 为兼容旧链接，直接走流式实现，默认chunkSize=8192
        return buildStreamResponse(fileId, 8192);
    }

    /**
     * PDF文件流式传输（支持自定义分片大小）
     */
    @GetMapping("/stream/pdf/{file_id}")
    @Operation(
            summary = "PDF 文件流式下载",
            description = "以流的方式返回 PDF 内容，支持指定 chunk_size（默认 8192 字节）"
    )
    public ResponseEntity<StreamingResponseBody> streamPdf(
            @Parameter(description = "文件ID", required = true)
            @PathVariable("file_id") String fileId,
            @Parameter(description = "单次写入的字节数，范围 1024~2097152")
            @RequestParam(value = "chunk_size", required = false, defaultValue = "8192") int chunkSize) {
        return buildStreamResponse(fileId, chunkSize);
    }

    /**
     * Word文档预览（转换为PDF后预览）
     */
    @GetMapping("/preview/word/{file_id}")
    @Operation(
            summary = "Word文档预览",
            description = "预览Word文档（转换为PDF后预览），返回PDF文件流"
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "200",
                    description = "预览成功",
                    content = @Content(mediaType = MediaType.APPLICATION_PDF_VALUE)
            ),
            @ApiResponse(
                    responseCode = "404",
                    description = "文件不存在",
                    content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)
            ),
            @ApiResponse(
                    responseCode = "422",
                    description = "验证错误或不支持的文件类型",
                    content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)
            )
    })
    public ResponseEntity<?> previewWord(
            @Parameter(description = "文件ID", required = true)
            @PathVariable("file_id") String fileId) {

        try {
            InputStream inputStream = java.util.Objects.requireNonNull(
                    filePreviewService.previewWord(fileId), "预览流为空");

            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_PDF_VALUE)
                    .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"preview.pdf\"")
                    .body(new InputStreamResource(inputStream));

        } catch (IllegalArgumentException e) {
            Map<String, Object> error = new HashMap<>();
            error.put("code", 200);
            error.put("message", e.getMessage());
            return ResponseEntity.ok().body(error);
        } catch (UnsupportedOperationException e) {
            Map<String, Object> error = new HashMap<>();
            error.put("code", 422);
            error.put("message", e.getMessage());
            error.put("total", 0);
            return ResponseEntity.status(HttpStatus.UNPROCESSABLE_ENTITY).body(error);
        } catch (Exception e) {
            Map<String, Object> error = new HashMap<>();
            error.put("code", 500);
            error.put("message", "预览失败: " + e.getMessage());
            error.put("total", 0);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
        }
    }

    private ResponseEntity<StreamingResponseBody> buildStreamResponse(String fileId, int chunkSize) {
        try {
            if (chunkSize < 1024 || chunkSize > 2_097_152) {
                return jsonStreamResponse(HttpStatus.BAD_REQUEST,
                        """
                        {"code":400,"message":"chunk_size 需要在 1024~2097152 之间"}
                        """);
            }

            InputStream inputStream = java.util.Objects.requireNonNull(
                    filePreviewService.previewPdf(fileId), "预览流为空");
            StreamingResponseBody body = outputStream -> {
                long written = 0;
                try (InputStream in = inputStream) {
                    byte[] buffer = new byte[chunkSize];
                    int len;
                    while ((len = in.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, len);
                        outputStream.flush();
                        written += len;
                    }
                }
                logger.info("流式输出完成: fileId={}, bytes={}", fileId, written);
            };

            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_PDF_VALUE)
                    .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"stream.pdf\"")
                    .body(body);

        } catch (IllegalArgumentException e) {
            return jsonStreamResponse(HttpStatus.NOT_FOUND,
                    """
                    {"code":404,"message":"%s"}
                    """.formatted(e.getMessage()));
        } catch (UnsupportedOperationException e) {
            return jsonStreamResponse(HttpStatus.UNPROCESSABLE_ENTITY,
                    """
                    {"code":422,"message":"%s"}
                    """.formatted(e.getMessage()));
        } catch (Exception e) {
            logger.error("流式传输PDF失败: fileId={}, error={}", fileId, e.getMessage(), e);
            return jsonStreamResponse(HttpStatus.INTERNAL_SERVER_ERROR,
                    """
                    {"code":500,"message":"文件传输失败: %s"}
                    """.formatted(e.getMessage()));
        }
    }

    private ResponseEntity<StreamingResponseBody> jsonStreamResponse(HttpStatus status, String json) {
        StreamingResponseBody body = outputStream ->
                outputStream.write(json.getBytes(StandardCharsets.UTF_8));
        return ResponseEntity.status(status.value())
                .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                .body(body);
    }

    /**
     * 查询所有文件的向量化状态统计
     */
    @GetMapping("/vectorization/stats")
    @Operation(
            summary = "查询文件向量化状态统计",
            description = "获取系统中所有文件的向量化状态统计信息，包括完成率、各状态文件数量等"
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "200",
                    description = "查询成功",
                    content = @Content(
                            mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = FileUploadResponse.VectorizationStats.class)
                    )
            ),
            @ApiResponse(
                    responseCode = "500",
                    description = "系统错误",
                    content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)
            )
    })
    public ResponseEntity<Map<String, Object>> getVectorizationStats() {
        Map<String, Object> response = new HashMap<>();

        try {
            // 查询所有文件
            List<File> allFiles = fileRepository.findAll();

            // 统计各种状态的文件数量
            int totalFiles = allFiles.size();
            int completedFiles = 0;
            int processingFiles = 0;
            int failedFiles = 0;
            int notStartedFiles = 0;

            for (File file : allFiles) {
                String status = file.getVectorizationStatus();
                if ("completed".equals(status)) {
                    completedFiles++;
                } else if ("processing".equals(status)) {
                    processingFiles++;
                } else if ("failed".equals(status)) {
                    failedFiles++;
                } else {
                    notStartedFiles++;
                }
            }

            // 计算完成率
            double completionRate = totalFiles > 0 ? (double) completedFiles / totalFiles : 0.0;

            // 获取最近的文件（按更新时间倒序，取前10个）
            List<File> recentFiles = allFiles.stream()
                    .sorted((f1, f2) -> f2.getUpdateTime().compareTo(f1.getUpdateTime()))
                    .limit(10)
                    .collect(java.util.stream.Collectors.toList());

            // 构建响应数据
            FileUploadResponse.VectorizationStats stats = new FileUploadResponse.VectorizationStats();
            stats.setTotalFiles(totalFiles);
            stats.setCompletedFiles(completedFiles);
            stats.setProcessingFiles(processingFiles);
            stats.setFailedFiles(failedFiles);
            stats.setNotStartedFiles(notStartedFiles);
            stats.setCompletionRate(completionRate);

            // 转换最近文件列表
            List<FileUploadResponse.VectorizationStatus> recentStatusList = recentFiles.stream()
                    .map(this::convertToVectorizationStatus)
                    .collect(java.util.stream.Collectors.toList());
            stats.setRecentFiles(recentStatusList);

            response.put("code", 0);
            response.put("message", "查询成功");
            response.put("data", stats);

            return ResponseEntity.ok(response);

        } catch (Exception e) {
            response.put("code", 500);
            response.put("message", "查询失败: " + e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        }
    }

    /**
     * 查询指定文件的向量化状态
     */
    @GetMapping("/vectorization/status/{file_id}")
    @Operation(
            summary = "查询指定文件的向量化状态",
            description = "根据文件ID查询特定文件的向量化状态信息"
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "200",
                    description = "查询成功",
                    content = @Content(
                            mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = FileUploadResponse.VectorizationStatus.class)
                    )
            ),
            @ApiResponse(
                    responseCode = "404",
                    description = "文件不存在",
                    content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)
            ),
            @ApiResponse(
                    responseCode = "500",
                    description = "系统错误",
                    content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)
            )
    })
    public ResponseEntity<Map<String, Object>> getFileVectorizationStatus(
            @Parameter(description = "文件ID", required = true)
            @PathVariable("file_id") String fileId) {

        Map<String, Object> response = new HashMap<>();

        try {
            java.util.Optional<File> fileOptional = fileRepository.findByFileId(fileId);
            if (!fileOptional.isPresent()) {
                response.put("code", 404);
                response.put("message", "文件不存在");
                response.put("total", 0);
                return ResponseEntity.ok().body(response);
            }
            File file = fileOptional.get();

            FileUploadResponse.VectorizationStatus status = convertToVectorizationStatus(file);

            response.put("code", 0);
            response.put("message", "查询成功");
            response.put("data", status);

            return ResponseEntity.ok(response);

        } catch (Exception e) {
            response.put("code", 500);
            response.put("message", "查询失败: " + e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        }
    }

    /**
     * 查询指定项目的文件向量化状态
     */
    @GetMapping("/vectorization/project/{project_id}")
    @Operation(
            summary = "查询项目文件的向量化状态",
            description = "根据项目ID查询该项目下所有文件的向量化状态信息"
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "200",
                    description = "查询成功",
                    content = @Content(
                            mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = FileUploadResponse.VectorizationStats.class)
                    )
            ),
            @ApiResponse(
                    responseCode = "500",
                    description = "系统错误",
                    content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)
            )
    })
    public ResponseEntity<Map<String, Object>> getProjectVectorizationStatus(
            @Parameter(description = "项目ID", required = true)
            @PathVariable("project_id") String projectId) {

        Map<String, Object> response = new HashMap<>();

        try {
            // 查询项目下的所有文件
            List<File> projectFiles = fileRepository.findByProjectId(projectId);

            // 统计各种状态的文件数量
            int totalFiles = projectFiles.size();
            int completedFiles = 0;
            int processingFiles = 0;
            int failedFiles = 0;
            int notStartedFiles = 0;

            for (File file : projectFiles) {
                String status = file.getVectorizationStatus();
                if ("completed".equals(status)) {
                    completedFiles++;
                } else if ("processing".equals(status)) {
                    processingFiles++;
                } else if ("failed".equals(status)) {
                    failedFiles++;
                } else {
                    notStartedFiles++;
                }
            }

            // 计算完成率
            double completionRate = totalFiles > 0 ? (double) completedFiles / totalFiles : 0.0;

            // 构建响应数据
            FileUploadResponse.VectorizationStats stats = new FileUploadResponse.VectorizationStats();
            stats.setTotalFiles(totalFiles);
            stats.setCompletedFiles(completedFiles);
            stats.setProcessingFiles(processingFiles);
            stats.setFailedFiles(failedFiles);
            stats.setNotStartedFiles(notStartedFiles);
            stats.setCompletionRate(completionRate);

            // 转换文件列表
            List<FileUploadResponse.VectorizationStatus> statusList = projectFiles.stream()
                    .map(this::convertToVectorizationStatus)
                    .collect(java.util.stream.Collectors.toList());
            stats.setRecentFiles(statusList);

            response.put("code", 0);
            response.put("message", "查询成功");
            response.put("data", stats);

            return ResponseEntity.ok(response);

        } catch (Exception e) {
            response.put("code", 500);
            response.put("message", "查询失败: " + e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        }
    }

    /**
     * 测试向量化健康检查
     */
    @GetMapping("/test/vectorization-health")
    @Operation(
            summary = "测试向量化健康检查",
            description = "测试向量化服务的健康检查功能"
    )
    public ResponseEntity<Map<String, Object>> testVectorizationHealth() {
        Map<String, Object> response = new HashMap<>();

        try {
            // 模拟健康检查逻辑
            List<File> allFiles = fileRepository.findAll();

            int totalFiles = allFiles.size();
            int completedFiles = 0;
            int processingFiles = 0;
            int failedFiles = 0;
            int notStartedFiles = 0;

            for (File file : allFiles) {
                String status = file.getVectorizationStatus();
                if ("completed".equals(status)) {
                    completedFiles++;
                } else if ("processing".equals(status)) {
                    processingFiles++;
                } else if ("failed".equals(status)) {
                    failedFiles++;
                } else {
                    notStartedFiles++;
                }
            }

            double completionRate = totalFiles > 0 ? (double) completedFiles / totalFiles : 0.0;

            Map<String, Object> healthData = new HashMap<>();
            healthData.put("service", "向量化服务");
            healthData.put("status", "UP");
            healthData.put("total_files", totalFiles);
            healthData.put("completed_files", completedFiles);
            healthData.put("processing_files", processingFiles);
            healthData.put("failed_files", failedFiles);
            healthData.put("not_started_files", notStartedFiles);
            healthData.put("completion_rate", String.format("%.2f%%", completionRate * 100));

            response.put("code", 0);
            response.put("message", "健康检查测试成功");
            response.put("data", healthData);

            return ResponseEntity.ok(response);

        } catch (Exception e) {
            response.put("code", 500);
            response.put("message", "健康检查测试失败: " + e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        }
    }

    /**
     * 查询项目文件信息
     */
    @GetMapping("/project/{project_id}/suppliers-files")
    @Operation(
            summary = "查询项目文件信息",
            description = "根据项目ID查询该项目的所有文件信息，返回标准格式：包含projectId、totalFiles、files列表和companyFiles分组"
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "200",
                    description = "查询成功",
                    content = @Content(
                            mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(example = "{\"code\":0,\"message\":\"查询成功\",\"data\":{\"projectId\":\"7654\",\"totalFiles\":6,\"files\":[...],\"companyFiles\":{\"公司1\":[\"文件1.pdf\"],\"公司2\":[\"文件2.pdf\"]}}}")
                    )
            ),
            @ApiResponse(
                    responseCode = "404",
                    description = "项目不存在",
                    content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)
            ),
            @ApiResponse(
                    responseCode = "500",
                    description = "系统错误",
                    content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)
            )
    })
    public ResponseEntity<Map<String, Object>> getProjectSuppliersAndFiles(
            @Parameter(description = "项目ID", required = true)
            @PathVariable("project_id") String projectId) {

        Map<String, Object> response = new HashMap<>();

        try {
            // 查询项目信息
            Project project = projectRepository.findByProjectId(projectId);
            if (project == null) {
                response.put("code", 404);
                response.put("message", "项目不存在");
                response.put("total", 0);
                return ResponseEntity.ok().body(response);
            }

            // 使用标准的 getProjectFiles 方法获取数据
            ProjectFilesResponse.ProjectFilesData data = fileService.getProjectFiles(projectId);

            response.put("code", 0);
            response.put("message", "查询成功");
            response.put("data", data);

            return ResponseEntity.ok(response);

        } catch (Exception e) {
            response.put("code", 500);
            response.put("message", "查询失败: " + e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        }
    }

    /**
     * 根据项目ID和供应商ID查询文件状态
     */
    @GetMapping("/project/{project_id}/supplier/{supplier_id}/status")
    @Operation(
            summary = "查询供应商文件状态",
            description = "根据项目ID和供应商ID查询该供应商的所有文件状态，包括文件ID、向量化状态和目录摘取状态"
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "200",
                    description = "查询成功",
                    content = @Content(
                            mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(example = "{\"code\":0,\"message\":\"查询成功\",\"data\":{\"files\":[{\"fileId\":\"xxx\",\"fileName\":\"文件1.pdf\",\"vectorizationStatus\":\"completed\",\"catalogExtractionStatus\":\"completed\"}]}}")
                    )
            ),
            @ApiResponse(
                    responseCode = "404",
                    description = "项目或供应商不存在",
                    content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)
            ),
            @ApiResponse(
                    responseCode = "500",
                    description = "系统错误",
                    content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)
            )
    })
    public ResponseEntity<Map<String, Object>> getSupplierFileStatus(
            @Parameter(description = "项目ID", required = true)
            @PathVariable("project_id") String projectId,
            @Parameter(description = "供应商ID", required = true)
            @PathVariable("supplier_id") String supplierId) {

        Map<String, Object> response = new HashMap<>();

        try {
            // 查询项目信息
            Project project = projectRepository.findByProjectId(projectId);
            if (project == null) {
                response.put("code", 404);
                response.put("message", "项目不存在");
                response.put("total", 0);
                return ResponseEntity.ok().body(response);
            }

            // 查询该项目和供应商下的所有文件
            List<File> files = fileRepository.findByProjectIdAndSupplierId(projectId, supplierId);

            if (files.isEmpty()) {
                response.put("code", 404);
                response.put("message", "未找到该供应商的文件");
                response.put("total", 0);
                return ResponseEntity.ok().body(response);
            }

            // 构建文件状态列表
            List<Map<String, Object>> fileStatusList = new ArrayList<>();
            for (File file : files) {
                Map<String, Object> fileStatus = new HashMap<>();
                fileStatus.put("fileId", file.getFileId());
                fileStatus.put("fileName", file.getFileName());
                fileStatus.put("fileExtension", file.getFileExtension());
                fileStatus.put("fileSize", file.getFileSize());
                
                // 向量化状态
                String vectorizationStatus = file.getVectorizationStatus();
                if (vectorizationStatus == null || vectorizationStatus.isEmpty()) {
                    vectorizationStatus = "not_started";
                }
                fileStatus.put("vectorizationStatus", vectorizationStatus);
                
                // 目录摘取状态：从文件实体中获取
                String catalogExtractionStatus = file.getCatalogExtractionStatus();
                if (catalogExtractionStatus == null || catalogExtractionStatus.isEmpty()) {
                    catalogExtractionStatus = "not_started";
                }
                fileStatus.put("catalogExtractionStatus", catalogExtractionStatus);
                
                // 目录摘取重试次数
                Integer retryCount = file.getCatalogExtractionRetryCount();
                if (retryCount == null) {
                    retryCount = 0;
                }
                fileStatus.put("catalogExtractionRetryCount", retryCount);
                
                // 目录数量
                long catalogCount = fileDirectoryRepository.countByFileId(file.getFileId());
                fileStatus.put("catalogCount", catalogCount);
                
                // 目录摘取完成时间
                if (file.getCatalogExtractionTime() != null) {
                    fileStatus.put("catalogExtractionTime", file.getCatalogExtractionTime());
                }
                
                // 添加其他有用信息
                fileStatus.put("createTime", file.getCreateTime());
                fileStatus.put("updateTime", file.getUpdateTime());
                
                fileStatusList.add(fileStatus);
            }

            // 构建响应数据
            Map<String, Object> data = new HashMap<>();
            data.put("projectId", projectId);
            data.put("supplierId", supplierId);
            data.put("totalFiles", files.size());
            data.put("files", fileStatusList);

            response.put("code", 0);
            response.put("message", "查询成功");
            response.put("data", data);

            return ResponseEntity.ok(response);

        } catch (Exception e) {
            logger.error("查询供应商文件状态失败: projectId={}, supplierId={}", projectId, supplierId, e);
            response.put("code", 500);
            response.put("message", "查询失败: " + e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        }
    }


    /**
     * 将File实体转换为VectorizationStatus DTO
     */
    private FileUploadResponse.VectorizationStatus convertToVectorizationStatus(File file) {
        FileUploadResponse.VectorizationStatus status = new FileUploadResponse.VectorizationStatus();
        status.setFileId(file.getFileId());
        status.setFileName(file.getFileName());
        status.setProjectId(file.getProjectId());
        status.setVectorizationStatus(file.getVectorizationStatus());
        status.setIsVectorized(file.getIsVectorized());
        status.setVectorizationCount(file.getVectorizationCount());
        status.setVectorizedTime(file.getVectorizedTime());
        status.setFileExtension(file.getFileExtension());
        status.setFileSize(file.getFileSize());
        return status;
    }

    @GetMapping("/project/{project_id}/files")
    @Operation(summary = "查询项目文件列表", description = "根据项目ID查询该项目下的所有文件信息")
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "查询成功"),
            @ApiResponse(responseCode = "404", description = "项目不存在")
    })
    public ResponseEntity<ProjectFilesResponse> getProjectFiles(
            @Parameter(description = "项目ID", required = true)
            @PathVariable("project_id") String projectId) {

        try {
            // 检查项目是否存在
            Project project = projectRepository.findByProjectId(projectId);
            if (project == null) {
                ProjectFilesResponse response = new ProjectFilesResponse();
                response.setCode(404);
                response.setMessage("项目不存在");
                return ResponseEntity.ok(response);
            }

            ProjectFilesResponse.ProjectFilesData data = fileService.getProjectFiles(projectId);

            ProjectFilesResponse response = new ProjectFilesResponse();
            response.setCode(0);
            response.setMessage("查询成功");
            response.setData(data);

            return ResponseEntity.ok(response);

        } catch (Exception e) {
            logger.error("查询项目文件失败: projectId={}", projectId, e);
            ProjectFilesResponse response = new ProjectFilesResponse();
            response.setCode(500);
            response.setMessage("系统错误: " + e.getMessage());
            return ResponseEntity.internalServerError().body(response);
        }
    }

    /**
     * 发送采购文件json信息接口 (ES平台调用)
     */
    @PostMapping("/upload")
    @Operation(summary = "发送采购文件json信息接口", description = "ES平台发送采购文件JSON信息")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "成功",
            content = @Content(schema = @Schema(implementation = FileUploadRequest.ApiResponse.class))),
        @ApiResponse(responseCode = "400", description = "参数错误"),
        @ApiResponse(responseCode = "401", description = "认证失败"),
        @ApiResponse(responseCode = "500", description = "系统错误")
    })
    public ResponseEntity<FileUploadRequest.ApiResponse> uploadProcurementFiles(
            @RequestHeader(value = "X-Server-Param", required = false) String xServerParam,
            @RequestHeader(value = "X-CurTime", required = false) String xCurTime,
            @RequestHeader(value = "X-CheckSum", required = false) String xCheckSum,
            @RequestHeader(value = "traceId", required = false) String traceId,
            @RequestBody FileUploadRequest.ResponseFileRequest request) {

        logger.info("接收文件上传请求: traceId={}, projectId={}, packageId={}, supplierId={}, fileType={}",
                   traceId, request.getProjectId(), request.getPackageId(), request.getSupplierId(), request.getFileType());

        try {
            // 验证认证信息
            if (!apiAuthUtils.validateAuth(xServerParam, xCurTime, xCheckSum, "your-app-id")) {
                logger.warn("文件上传认证失败: traceId={}", traceId);
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                    .body(new FileUploadRequest.ApiResponse("401", "认证失败"));
            }

            // 验证请求参数
            if (request.getProjectId() == null || request.getPackageId() == null ||
                request.getFileIds() == null || request.getFileIds().isEmpty()) {
                return ResponseEntity.badRequest()
                    .body(new FileUploadRequest.ApiResponse("400", "缺少必需参数"));
            }

            // 判断是采购文件还是供应商应答文件
            if (request.getSupplierId() != null && !request.getSupplierId().isEmpty()) {
                // 供应商应答文件逻辑
                String fileType = request.getFileType();
                
                // 按照请求的fileType：1商务、2技术
                // 只获取技术文件(2)，其他的只接受请求返回200
                if ("1".equals(fileType)) {
                    logger.info("接收到商务文件，忽略处理: traceId={}, supplierId={}", traceId, request.getSupplierId());
                    return ResponseEntity.ok(new FileUploadRequest.ApiResponse("0", "成功"));
                } else if ("2".equals(fileType)) {
                    // 技术文件，进行下载和处理
                    logger.info("接收到技术文件，开始处理: traceId={}, supplierId={}", traceId, request.getSupplierId());
                    fileService.processResponseFilesAsync(request.getProjectId(), request.getPackageId(),
                                                        request.getSupplierId(), request.getFileIds(),
                                                        request.getFileType(), request.getJsonFileId(),
                                                        request.getUnitId(), traceId);
                } else {
                    // 其他类型，暂时也忽略或按需处理，这里默认忽略
                    logger.info("接收到其他类型文件({}), 忽略处理: traceId={}, supplierId={}", fileType, traceId, request.getSupplierId());
                    return ResponseEntity.ok(new FileUploadRequest.ApiResponse("0", "成功"));
                }
            } else {
                // 采购文件逻辑 (没有supplierId)
                fileService.processProcurementFilesAsync(request.getProjectId(), request.getPackageId(),
                                                       request.getFileIds(), traceId);
            }

            logger.info("文件上传请求处理完成: traceId={}", traceId);
            return ResponseEntity.ok(new FileUploadRequest.ApiResponse("0", "成功"));

        } catch (Exception e) {
            logger.error("文件上传处理失败: traceId={}", traceId, e);
            return ResponseEntity.internalServerError()
                .body(new FileUploadRequest.ApiResponse("500", "系统错误: " + e.getMessage()));
        }
    }

    /**
     * 发送应答文件信息接口 (ES平台调用)
     */
    @PostMapping("/upload/response")
    @Operation(summary = "发送应答文件信息接口", description = "ES平台发送供应商应答文件信息")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "成功",
            content = @Content(schema = @Schema(implementation = FileUploadRequest.ApiResponse.class))),
        @ApiResponse(responseCode = "400", description = "参数错误"),
        @ApiResponse(responseCode = "401", description = "认证失败"),
        @ApiResponse(responseCode = "500", description = "系统错误")
    })
    public ResponseEntity<FileUploadRequest.ApiResponse> uploadResponseFiles(
            @RequestHeader(value = "X-Server-Param", required = false) String xServerParam,
            @RequestHeader(value = "X-CurTime", required = false) String xCurTime,
            @RequestHeader(value = "X-CheckSum", required = false) String xCheckSum,
            @RequestHeader(value = "traceId", required = false) String traceId,
            @RequestBody FileUploadRequest.ResponseFileRequest request) {

        logger.info("接收应答文件上传请求: traceId={}, projectId={}, supplierId={}",
                   traceId, request.getProjectId(), request.getSupplierId());

        try {
            // 验证认证信息
            if (!apiAuthUtils.validateAuth(xServerParam, xCurTime, xCheckSum, "your-app-id")) {
                logger.warn("应答文件上传认证失败: traceId={}", traceId);
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                    .body(new FileUploadRequest.ApiResponse("401", "认证失败"));
            }

            // 验证请求参数
            if (request.getProjectId() == null || request.getPackageId() == null ||
                request.getSupplierId() == null || request.getFileIds() == null ||
                request.getFileIds().isEmpty() || request.getUnitId() == null) {
                return ResponseEntity.badRequest()
                    .body(new FileUploadRequest.ApiResponse("400", "缺少必需参数"));
            }

            // 异步下载和处理文件
            fileService.processResponseFilesAsync(request.getProjectId(), request.getPackageId(),
                                                request.getSupplierId(), request.getFileIds(),
                                                request.getFileType(), request.getJsonFileId(),
                                                request.getUnitId(), traceId);

            logger.info("应答文件上传请求处理完成: traceId={}", traceId);
            return ResponseEntity.ok(new FileUploadRequest.ApiResponse("0", "成功"));

        } catch (Exception e) {
            logger.error("应答文件上传处理失败: traceId={}", traceId, e);
            return ResponseEntity.internalServerError()
                .body(new FileUploadRequest.ApiResponse("500", "系统错误: " + e.getMessage()));
        }
    }
}

