package com.ruoyi.file;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.annotation.Dev;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.file.FileUtils;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.time.Duration;

@RestController
@RequiredArgsConstructor
@RequestMapping("/file/upload/")
@SaIgnore
public class FileUploadApi {

  public final FileService fileService;


  /**
   * 获取上传凭证，
   * 实际业务中，需要在对应的业务中完成凭证的获取
   *
   * @return
   */
  @GetMapping("getUploadKey")
  @Dev
  public R getUploadKey() {
    return R.ok().setData(FileUtils.getUploadKey());
  }

  /**
   * 删除上传凭证
   *
   * @param key
   */
  @GetMapping("removeUploadKey-{key}")
  public void removeUploadKey(@PathVariable String key) {
    FileUtils.removeUploadKey(key);
  }

  @GetMapping("exitisUploadKey-{key}")
  public Boolean exitisUploadKey(@PathVariable String key) {
    return FileUtils.exitisUploadKey(key);
  }


  /**
   * 上传文件
   *
   * @param file
   * @param prefix
   * @param key
   * @param keepFilename
   * @return
   */
  @PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
  public R upload(@RequestPart("file") MultipartFile file, String prefix, String key, @RequestParam(defaultValue = "false") Boolean keepFilename) {
    if (ObjectUtil.isNull(file)) {
      throw new ServiceException("文件必填");
    }
    if (!FileUtils.exitisUploadKey(key)) {
      throw new ServiceException("上传凭证无效");
    }
    return R.ok().setData(fileService.setPrefix(prefix).setKeepFilename(keepFilename).save(file));
  }


  @PostMapping("multipartUploadInit")
  public R multipartUploadInit(String filename, String prefix, String key, @RequestParam(defaultValue = "false") Boolean keepFilename) {
    if (StrUtil.isBlank(filename)) {
      throw new ServiceException("文件名必填");
    }
    if (!FileUtils.exitisUploadKey(key)) {
      throw new ServiceException("上传凭证无效");
    }
    return R.ok().setData(fileService.setPrefix(prefix).setFilename(filename).setKeepFilename(keepFilename).multipartUploadInit());
  }

  @PostMapping(value = "multipartUpload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
  @SneakyThrows
  public R multipartUpload(@RequestPart("file") MultipartFile file, String uploadId, Integer partNumber) {
    if (StrUtil.isBlank(uploadId)) {
      throw new ServiceException("上传标识必填");
    }
    fileService.multipartUpload(uploadId, partNumber, file.getInputStream());
    return R.ok();
  }

  @GetMapping("multipartUploadListParts")
  public R multipartUploadListParts(String uploadId) {
    if (StrUtil.isBlank(uploadId)) {
      throw new ServiceException("上传标识必填");
    }
    return R.ok().setData(fileService.multipartUploadListParts(uploadId));
  }

  @PostMapping("multipartUploadComplete")
  public R multipartUploadComplete(String uploadId) {
    if (StrUtil.isBlank(uploadId)) {
      throw new ServiceException("上传标识必填");
    }
    return R.ok().setData(fileService.multipartUploadComplete(uploadId));
  }

  @PostMapping("multipartUploadAbort")
  public R multipartUploadAbort(String uploadId) {
    if (StrUtil.isBlank(uploadId)) {
      throw new ServiceException("上传标识必填");
    }
    try {
      fileService.multipartUploadAbort(uploadId);
    } catch (Exception e) {

    }
    return R.ok();
  }


  /**
   * 上传图片
   *
   * @param file
   * @param prefix
   * @param key
   * @param saveSrc
   * @param saveThumbnail
   * @return
   */
  @PostMapping(value = "image", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
  public R uploadImage(@RequestPart("file") MultipartFile file, String prefix, String key,
                       @RequestParam(defaultValue = "false") Boolean saveSrc,
                       @RequestParam(defaultValue = "true") Boolean watermark,
                       @RequestParam(defaultValue = "true") Boolean saveThumbnail
  ) {
    if (ObjectUtil.isNull(file)) {
      throw new ServiceException("文件必填");
    }
    if (!FileUtils.exitisUploadKey(key)) {
      throw new ServiceException("上传凭证无效");
    }

    return R.ok().setData(fileService.setPrefix(prefix).setWatermark(watermark).setSaveSrc(saveSrc).setThumbnail(saveThumbnail).saveImage(file));
  }

  @GetMapping("/download")
  @SneakyThrows
  public ModelAndView downloadFile(String url, String key, HttpServletRequest request, HttpServletResponse response) {
    if (StrUtil.isBlank(url)) {
      response.sendError(404, "URL不能为空");
      return null;
    }
    if (!FileUtils.exitisUploadKey(key)) {
      response.sendError(404, "上传凭证无效");
      return null;
    }
    fileService.download(url, Duration.ofHours(1), request, response);
    return null;
  }

  @PostMapping("/remove")
  public R remove(String url, String key){
    if (StrUtil.isBlank(url)) {
      throw new ServiceException("URL不能为空");
    }
    if (!FileUtils.exitisUploadKey(key)) {
      throw new ServiceException("上传凭证无效");
    }
    fileService.delete(url);
    return R.ok();
  }

}
