package com.ruoyi.web.controller.file;

import com.cclotus.cms.service.FileManagerService;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.common.utils.file.MimeTypeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;

@RestController
@RequestMapping("/file-manager")
public class FileManagerController {

    @Autowired
    private FileManagerService service;

    private static final Logger log = LoggerFactory.getLogger(FileManagerController.class);

    /**
     * 文件下载请求
     *
     * @param fileName 文件名称
     * @param path     文件路径
     */
    @PostMapping("/download")
    public void fileDownload(String fileName, String path, HttpServletResponse response) {
        checkPath(path);
        checkFileName(fileName);
        try {
            if (!FileUtils.checkAllowDownload(fileName)) {
                throw new Exception(StringUtils.format("文件名称({})非法，不允许下载。 ", fileName));
            }
            String filePath = service.getMediaPath() + path + "/" + fileName;
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, fileName);
            FileUtils.writeBytes(filePath, response.getOutputStream());
        } catch (Exception e) {
            log.error("下载文件失败", e);
        }
    }

    /**
     * 文件上传请求（单个）
     */
    @PostMapping("/upload")
    public AjaxResult uploadFile(MultipartFile file, String path) {
        checkPath(path);
        try {
            // 上传文件路径
            String filePath = service.getMediaPath() + path;
            String newName = service.getFileName(filePath, file.getOriginalFilename());
            // 上传并返回新文件名称
            String fileName = FileUploadUtils.uploadWithName(filePath, newName, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
            AjaxResult ajax = AjaxResult.success();
            ajax.put("url", fileName);
            ajax.put("fileName", fileName);
            ajax.put("newFileName", FileUtils.getName(fileName));
            ajax.put("originalFilename", file.getOriginalFilename());
            return ajax;
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 打开指定文件夹
     *
     * @param path 文件路径
     * @return 指定文件路径下的文件和文件夹信息
     */
    @GetMapping("/open")
    public AjaxResult openDirectory(String path) {
        checkPath(path);
        return AjaxResult.success(service.browseDirectory(path));
    }

    /**
     * 获取所有目录信息
     *
     * @return 目录信息
     */
    @GetMapping("/directories")
    public AjaxResult getDirectories() {
        return AjaxResult.success(service.directoryTree(null));
    }

    /**
     * 创建文件夹
     *
     * @param path    文件路径
     * @param dirName 创建的文件夹名称
     * @return 创建结果
     */
    @PostMapping("/create")
    public AjaxResult createDirectory(String path, String dirName) {
        checkPath(path);
        checkFileName(dirName);
        service.createDirectory(path, dirName);
        return AjaxResult.success();
    }

    /**
     * 修改文件或文件夹名称
     *
     * @param path       文件所属路径
     * @param originName 原始名称
     * @param newName    新名称
     * @return 修改结果
     */
    @PostMapping("/rename")
    public AjaxResult changeFileName(String path, String originName, String newName) {
        checkPath(path);
        checkFileName(newName);
        service.changeFileName(path, originName, newName);
        return AjaxResult.success();
    }

    /**
     * 删除文件或者文件夹
     *
     * @param path      当前文件所在路径
     * @param name      文件或者文件夹名称
     * @param mandatory 是否强制删除文件夹内容，默认为否
     * @return 删除结果
     */
    @DeleteMapping("/delete")
    public AjaxResult delete(String path, String name) {
        checkPath(path);
        checkFileName(name);
        service.delete(path, name, false);
        return AjaxResult.success();
    }

    /**
     * 检查路径
     *
     * @param path 文件路径
     * @return
     */
    private Boolean checkPath(String path) {
        if (path == null || path.isEmpty()) return true;
        if (path.contains("..")) throw new ServiceException("文件路径不合法");
        return true;
    }

    /**
     * 检查文件名称
     *
     * @param fileName 文件名
     * @return
     */
    private Boolean checkFileName(String fileName) {
        if (fileName == null || fileName.isEmpty()) throw new ServiceException("文件名不合法");
        if (fileName.contains("..")) throw new ServiceException("文件名不合法");
        return true;
    }

}
