package com.goldenwater.slaj.acci.controller;

import java.io.*;
import java.util.UUID;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import com.goldenwater.common.core.domain.AjaxResult;

/**
 * 大文件分块上传控制器 — 解决事故月报附件（图片、PDF、视频等）因文件过大导致上传超时的问题。
 * 前端将大文件切分为多个小块依次上传，后端暂存到临时目录；当最后一个块到达时触发合并，
 * 将全部分块按顺序拼接成完整文件并生成 UUID 文件名。合并后自动清理临时分块文件。
 * 分块上传优于直接上传：①突破 HTTP 请求体大小限制；②支持断点续传（前端控制）；
 * ③上传进度可精确到块级别。
 */
@RestController
@RequestMapping("/acci/file")
public class ChunkUploadController {

    private String uploadPath = System.getProperty("java.io.tmpdir") + "/upload/";

    /**
     * 分块上传核心方法 — 接收前端上传的单个分块并保存到临时目录。
     * 每块文件命名为 "{chunkIndex}_{原始文件名}"，写入系统临时目录。
     * 当 {@code chunk + 1 == chunks}（即当前为最后一块）时触发合并操作：
     * 按块索引 0..n-1 顺序读取所有分块、写入目标文件、删除临时分块。
     *
     * @param file   当前分块的二进制内容
     * @param chunk  当前分块的索引（从 0 开始）
     * @param chunks 总分块数
     * @param name   原始文件名（所有分块共用，用于识别归属同一文件）
     */
    @PostMapping("/upload")
    public AjaxResult upload(
            @RequestParam("file") MultipartFile file,
            @RequestParam(value = "chunk", required = false, defaultValue = "0") Integer chunk,
            @RequestParam(value = "chunks", required = false, defaultValue = "1") Integer chunks,
            @RequestParam("name") String name) {
        try {
            File dir = new File(uploadPath);
            if (!dir.exists()) dir.mkdirs();

            File tempFile = new File(uploadPath, chunk + "_" + name);
            file.transferTo(tempFile);

            if (chunk + 1 == chunks) {
                String newFileName = UUID.randomUUID().toString().replace("-", "")
                        + "." + FilenameUtils.getExtension(name);
                File outputFile = new File(uploadPath, newFileName);
                try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outputFile))) {
                    for (int i = 0; i < chunks; i++) {
                        File f = new File(uploadPath, i + "_" + name);
                        byte[] bytes = FileUtils.readFileToByteArray(f);
                        bos.write(bytes);
                        bos.flush();
                        f.delete();
                    }
                }
                return AjaxResult.success("上传成功", newFileName);
            }
            return AjaxResult.success("分块上传成功");
        } catch (IOException e) {
            return AjaxResult.error("上传失败: " + e.getMessage());
        }
    }
}
