package com.philisense.www.controller.web;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.CharUtil;
import com.philisense.www.annotation.log.OperateLog;
import com.philisense.www.config.OssStorageProperties;
import com.philisense.www.common.config.CommonConst;
import com.philisense.www.controller.BaseUtilController;
import com.philisense.www.core.text.Convert;
import com.philisense.www.enums.MimeTypeEnum;
import com.philisense.www.exception.ServiceException;
import com.philisense.www.factory.OssStorageFactory;
import com.philisense.www.service.SystemNoticeFileService;
import com.philisense.www.utils.ActiveUserUtils;
import com.philisense.www.utils.AssertUtils;
import com.philisense.www.utils.StorageUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
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.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;


/**
 * 文件上传
 */
@RestController
@RequestMapping(CommonConst.WEB_REST_SERVICE_PREFICX+"uploading")
@Api(tags = "UploadingControllerForWeb|一个用来操作-{文件上传}-业务模块的控制器")
public class UploadingControllerForWeb extends BaseUtilController {

    @Autowired
    OssStorageProperties config;
    @Autowired
    private SystemNoticeFileService systemNoticeFileService;

    /**
     * 普通上传文件
     *
     * @param uploadFile
     * @param
     * @return
     */
    @PostMapping("/uploadSingleFile")
    @ApiOperation(value = "根据-{文件上传}-普通文件上传", notes = "成功返回:{\"success\":true,\"message\",\"数据插入成功\"},失败返回:{\"success\":false,\"message\",\"数据插入失败\"}")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "body", name = "file", value = "file", required = true, dataType = "File", dataTypeClass = File.class),
            @ApiImplicitParam(paramType = "body", name = "noticeid", value = "业务id", required = true, dataTypeClass = String.class),
            @ApiImplicitParam(paramType = "body", name = "businessfiletype", value = "业务类型", required = true, dataTypeClass = String.class)
    })
    @OperateLog(name = "根据-{文件上传}-普通文件上传", value = "insert", type = "PC")
    public Map<String, Object> uploadSingleFile(@RequestParam("file") MultipartFile uploadFile, String noticeid, String businessfiletype) {
        Map<String, Object> result = new HashMap<String, Object>();

        try {
            // 判断文件
            AssertUtils.isNull(uploadFile, "参数不能为空");

            Map<String, Object> resultMap = new HashMap<String, Object>();
            String id = UUID.randomUUID().toString().replace("-", "");

            String md5key = StorageUtils.md5HashCode(uploadFile.getInputStream());
            String path = new StringBuffer()
                    .append(sdf_time.format(new Date()))
                    .append(CharUtil.SLASH)
                    .append(md5key)
                    .append(CharUtil.SLASH)
                    .append(id)
                    .append(CharUtil.SLASH)
                    .append(uploadFile.getOriginalFilename()).toString();
            Map<String, Object> fileMap = OssStorageFactory.build().upload(uploadFile, path);

            // 文件名
            String originalFilename = uploadFile.getOriginalFilename();
            // 扩展名
            String extName = StorageUtils.getFileType(originalFilename);

            resultMap.put("md5key", md5key);
            resultMap.put("filename", originalFilename);
            resultMap.put("newfilename", originalFilename);
            resultMap.put("filepath", fileMap.get("path"));
            resultMap.put("fileurl", fileMap.get("url"));
            resultMap.put("filetype", extName);
            resultMap.put("filesuffix", extName);
            resultMap.put("filesize", uploadFile.getSize());
            resultMap.put("mimetype", MimeTypeEnum.getMimeType(extName));
            resultMap.put("storagetype", config.getOssType().getValue());
            resultMap.put("id", id);
            resultMap.put("noticeid", noticeid);
            resultMap.put("businessfiletype", businessfiletype);
            resultMap.put("uploadtime", new Date());
            resultMap.put("apply_user_id", ActiveUserUtils.getUserId());
            resultMap.put("apply_user", ActiveUserUtils.getUserNameCn());

//            systemNoticeFileService.insert(resultMap);

            result.put(DATASUCCESS, SUCCESSFLAG);
            result.put(DATAMESSAGE, UPLOAD_SUCCESS_MSG);
            result.put(DATARECORD, resultMap);
        } catch (Exception e) {
            e.printStackTrace();
            result.put(DATASUCCESS, ERRORFLAG);
            result.put(DATAMESSAGE, UPLOAD_FAIL_MSG + e.getMessage());
        }

        return result;
    }

    /**
     * 替换上传文件
     *
     * @param uploadFile
     * @param
     * @return
     */
    @PostMapping("/uploadReplaceSingleFile")
    @ApiOperation(value = "根据-{文件上传}-普通文件上传", notes = "成功返回:{\"success\":true,\"message\",\"数据插入成功\"},失败返回:{\"success\":false,\"message\",\"数据插入失败\"}")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "body", name = "file", value = "file", required = true, dataType = "File", dataTypeClass = File.class),
            @ApiImplicitParam(paramType = "body", name = "fileId", value = "文件ID", required = true, dataTypeClass = String.class)
    })
    @OperateLog(name = "根据-{文件上传}-普通文件上传", value = "insert", type = "PC")
    public Map<String, Object> uploadReplaceSingleFile(@RequestParam("file") MultipartFile uploadFile, String fileId) {
        Map<String, Object> result = new HashMap<String, Object>();

        try {
            // 判断文件
            AssertUtils.isNull(uploadFile, "参数不能为空");

            Map<String, Object> vars = new HashMap<>();
            vars.put("id", fileId);
            Map<String, Object> resultMap = systemNoticeFileService.getOne(vars);
            AssertUtils.isNull(resultMap, "未查询到相关附件");

            String filePath = Convert.toStr(resultMap.get("filepath"), "");
            AssertUtils.isNull(filePath, "未查询到相关附件");

            String md5key = StorageUtils.md5HashCode(uploadFile.getInputStream());
            String path = new StringBuffer()
                    .append(sdf_time.format(new Date()))
                    .append(CharUtil.SLASH)
                    .append(md5key)
                    .append(CharUtil.SLASH)
                    .append(fileId)
                    .append(CharUtil.SLASH)
                    .append(uploadFile.getOriginalFilename()).toString();
            Map<String, Object> fileMap = OssStorageFactory.build().upload(uploadFile, path);

            // 文件名
            String originalFilename = uploadFile.getOriginalFilename();
            // 扩展名
            String extName = StorageUtils.getFileType(originalFilename);

            resultMap.put("md5key", md5key);
            resultMap.put("filename", originalFilename);
            resultMap.put("newfilename", originalFilename);
            resultMap.put("filepath", fileMap.get("path"));
            resultMap.put("fileurl", fileMap.get("url"));
            resultMap.put("filetype", extName);
            resultMap.put("filesuffix", extName);
            resultMap.put("filesize", uploadFile.getSize());
            resultMap.put("mimetype", MimeTypeEnum.getMimeType(extName));
            resultMap.put("storagetype", config.getOssType().getValue());
            resultMap.put("uploadtime", new Date());
            resultMap.put("apply_user_id", ActiveUserUtils.getUserId());
            resultMap.put("apply_user", ActiveUserUtils.getUserNameCn());
//            systemNoticeFileService.update(resultMap);

            if(!filePath.equals(path)) {
                OssStorageFactory.build().delete(filePath);
            }

            result.put(DATASUCCESS, SUCCESSFLAG);
            result.put(DATAMESSAGE, UPLOAD_SUCCESS_MSG);
            result.put(DATARECORD, resultMap);
        } catch (Exception e) {
            e.printStackTrace();
            result.put(DATASUCCESS, ERRORFLAG);
            result.put(DATAMESSAGE, UPLOAD_FAIL_MSG + e.getMessage());
        }

        return result;
    }

    @GetMapping("/getUrl/{fileId}")
    @ApiOperation(value = "根据-{文件上传}-获取文件路径", notes = "成功返回:{\"success\":true,\"message\",\"数据插入成功\"},失败返回:{\"success\":false,\"message\",\"数据插入失败\"}")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "body", name = "fileId", value = "文件路径", required = true, dataTypeClass = String.class)
    })
    @OperateLog(name = "根据-{文件上传}-获取文件路径", value = "query", type = "PC")
    public Map<String, Object> getUrl(HttpServletRequest request, HttpServletResponse response, @PathVariable("fileId") String fileId) {
        Map<String, Object> result = new HashMap<String, Object>();
        try {
            AssertUtils.isNull(fileId, "文件id不能为空");
            Map<String, Object> vars = new HashMap<>();
            vars.put("id", fileId);
            Map<String, Object> fileMap = systemNoticeFileService.getOne(vars);
            AssertUtils.isNull(fileMap, "未查询到相关附件");
            String filePath = Convert.toStr(fileMap.get("filepath"), "");
            AssertUtils.isNull(filePath, "未查询到相关附件");

            String url = OssStorageFactory.build().getUrl(filePath);

            result.put(DATASUCCESS, SUCCESSFLAG);
            result.put(DATAMESSAGE, QUERY_SUCCESS_MSG);
            result.put(DATARECORD, url);
        } catch (Exception e) {
            result.put(DATASUCCESS, ERRORFLAG);
            result.put(DATAMESSAGE, QUERY_FAIL_MSG + e.getMessage());
        }
        return result;
    }

    /**
     * 下载
     */
    @GetMapping("/download/{fileId}")
    @ApiOperation(value = "根据-{文件上传}-获取文件路径", notes = "成功返回:{\"success\":true,\"message\",\"数据插入成功\"},失败返回:{\"success\":false,\"message\",\"数据插入失败\"}")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "body", name = "fileId", value = "文件路径", required = true, dataTypeClass = String.class)
    })
    @OperateLog(name = "根据-{文件上传}-获取文件路径", value = "query", type = "PC")
    public void downloadFile(HttpServletRequest request, HttpServletResponse response, @PathVariable("fileId") String fileId) {
        try {
            AssertUtils.isNull(fileId, "文件id不能为空");
            Map<String, Object> vars = new HashMap<>();
            vars.put("id", fileId);
            Map<String, Object> fileMap = systemNoticeFileService.getOne(vars);
            AssertUtils.isNull(fileMap, "未查询到相关附件");

            String filePath = Convert.toStr(fileMap.get("filepath"), "");
            AssertUtils.isNull(filePath, "未查询到相关附件");

            // 下载名称
            String fileName = Convert.toStr(fileMap.get("filename"), "");
            InputStream inputStream = OssStorageFactory.build().download(filePath);
            //response为HttpServletResponse对象
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
            response.setHeader("Content-Disposition","attachment;filename=" + fileName);
            ServletOutputStream out = response.getOutputStream();
            IoUtil.copy(inputStream, out);
            //此处记得关闭输出Servlet流
            IoUtil.close(out);
            IoUtil.close(inputStream);
        } catch (Exception e){
            throw new ServiceException(e.getMessage());
        }
    }

    @GetMapping("/delete/{fileId}")
    @ApiOperation(value = "根据-{文件上传}-删除文件", notes = "成功返回:{\"success\":true,\"message\",\"数据插入成功\"},失败返回:{\"success\":false,\"message\",\"数据插入失败\"}")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "body", name = "fileId", value = "文件路径", required = true, dataTypeClass = String.class)
    })
    @OperateLog(name = "根据-{文件上传}-删除文件", value = "query", type = "PC")
    public Map<String, Object> deleteFile(HttpServletRequest request, HttpServletResponse response, @PathVariable("fileId") String fileId) {
        Map<String, Object> result = new HashMap<String, Object>();
        try {
            AssertUtils.isNull(fileId, "文件id不能为空");
            Map<String, Object> vars = new HashMap<>();
            vars.put("id", fileId);
            Map<String, Object> fileMap = systemNoticeFileService.getOne(vars);
            AssertUtils.isNull(fileMap, "未查询到相关附件");

            String filePath = Convert.toStr(fileMap.get("filepath"), "");
            AssertUtils.isNull(filePath, "未查询到相关附件");

            OssStorageFactory.build().delete(filePath);
            systemNoticeFileService.deleteByPrimaryKey(fileId);

            result.put(DATASUCCESS, SUCCESSFLAG);
            result.put(DATAMESSAGE, DELETE_SUCCESS_MSG);
        } catch (Exception e) {
            result.put(DATASUCCESS, ERRORFLAG);
            result.put(DATAMESSAGE, DELETE_FAIL_MSG + e.getMessage());
        }
        return result;
    }
}
