package cc.smtweb.system.bpm.spring.controller;

import cc.smtweb.framework.core.cache.redis.RedisManager;
import cc.smtweb.framework.core.common.R;
import cc.smtweb.framework.core.db.DbEngine;
import cc.smtweb.framework.core.session.SessionUtil;
import cc.smtweb.system.bpm.spring.dao.ImageAttachDao;
import cc.smtweb.system.bpm.spring.entity.FileDataVO;
import cc.smtweb.system.bpm.spring.entity.UploadDataVO;
import cc.smtweb.system.bpm.util.FilePathGenerator;
import cc.smtweb.system.bpm.util.FilePathInfo;
import cc.smtweb.system.bpm.util.MemMultipartFile;
import cc.smtweb.system.bpm.util.ThumbImage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;

@RestController
public class FileUploadController {
    @Autowired
    private FilePathGenerator filePathGenerator;

    @Autowired
    private DbEngine dbEngine;

    @Autowired
    private ImageAttachDao imageAttachDao;

    // TODO: 权限处理，临时文件处理
    @PostMapping("/fs/upload/{path}")
    public R upload(@RequestParam("file") MultipartFile file, @PathVariable("path") String path,
                    @RequestParam(value = "thumb", required = false) String thumb,
                    @RequestParam(value = "thumbHeight", required = false) Integer thumbHeight,
                    @RequestParam(value = "commit", required = false) Boolean insert,
                    @RequestParam(value = "keepName", required = false) Boolean keepName,
                    HttpServletRequest request
    ) {
        return uploadFile(path, file, ThumbImage.type(thumb), thumbHeight, insert, keepName);
    }

    @PostMapping("/fs/uploadImage/{path}")
    public R upload(@RequestBody FileDataVO data, @PathVariable("path") String path,
                    @RequestParam(value = "thumb", required = false) String thumb,
                    @RequestParam(value = "thumbHeight", required = false) Integer thumbHeight,
                    @RequestParam(value = "commit", required = false) Boolean insert,
                    HttpServletRequest request) {
        MultipartFile file = MemMultipartFile.build(data.getData());
        if (file == null) {
            return R.error("数据内容格式有错");
        }

        return uploadFile(path, file, ThumbImage.type(thumb), thumbHeight, insert, false);
    }

    @PostMapping("/fs/uploadAvatar/{path}")
    public R uploadAvatar(@RequestParam("file") MultipartFile file, @PathVariable("path") String path,
                          @RequestParam(value = "size", required = false) Integer size,
                          @RequestParam(value = "commit", required = false) Boolean insert,
                          @RequestParam(value = "keepName", required = false) Boolean keepName,
                          HttpServletRequest request) {
        return uploadFile(path, file, ThumbImage.TYPE_AVATAR, size, insert, keepName);
    }

    // 保存文件和插入数据库数据
    @PostMapping("/fs/commit/{path}")
    public R commit(@RequestParam("file") MultipartFile file, @PathVariable("path") String path,
                    @RequestParam(value = "thumb", required = false) String thumb,
                    @RequestParam(value = "thumbHeight", required = false) Integer thumbHeight,
                    @RequestParam(value = "keepName", required = false) Boolean keepName,
                    HttpServletRequest request) {
        return uploadFile(path, file, ThumbImage.type(thumb), thumbHeight, true, keepName);
    }

    private R uploadFile(String path, MultipartFile file, int type, Integer size, Boolean insert, Boolean keepName) {
        //获取上传时的文件名
        String fileName = file.getOriginalFilename();

        //判断文件是否为空
        if (file.isEmpty() && fileName != null) {
            return R.error("文件为空");
        }

        // 判断保持文件名不变
        FilePathInfo fileInfo = filePathGenerator.make(path, fileName, Boolean.TRUE.equals(keepName));

        // 注意是路径+文件名
        File targetFile = new File(fileInfo.getFullFileName());

        try (InputStream inputStream = file.getInputStream(); OutputStream outputStream = new FileOutputStream(targetFile)) {
            // 最后使用资源访问器FileCopyUtils的copy方法拷贝文件
            FileCopyUtils.copy(inputStream, outputStream);
        } catch (IOException e) {
            //出现异常，则告诉页面失败
            return R.error("上传失败", e);
        }

        // 生成缩略图
//    String contentType = file.getContentType();
        UploadDataVO data = new UploadDataVO();

        data.setPath(fileInfo.getMysqlFilePath());
        data.setName(fileName);
        data.setSize(file.getSize());
        data.setContentType(file.getContentType());
        data.setUrl(filePathGenerator.getFileUrl(fileInfo.getMysqlFilePath()));

        if (type == ThumbImage.TYPE_THUMB || type == ThumbImage.TYPE_AVATAR) {
            try {
                imageAttachDao.makeThumb(data, type == ThumbImage.TYPE_THUMB, targetFile, size);
            } catch (IOException e) {
                return R.error("生成缩略图失败", e);
            }
        }

        if (Boolean.TRUE.equals(insert)) {
            Long id = dbEngine.nextId();
            Timestamp now = new Timestamp(System.currentTimeMillis());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");

            dbEngine.update("insert into sw_user.sys_attach(attach_id, attach_name, attach_path, attach_content_type, attach_size, attach_create_time) values(?, ?, ?, ?, ?, ?)",
                    id, data.getName(), data.getPath(), data.getContentType(), data.getSize(), sdf.format(now));

            data.setId(id);
        }

        return R.success(data);
    }

    // TODO: 修改为安全的后台删除方式
    @PostMapping("/fs/remove")
    public R remove(@RequestParam(value = "filePath") String filePath, HttpServletRequest request) {
        File file = new File(filePathGenerator.getFileDiskPath(filePath));
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                R.success(filePath);
            }
        }

        return R.success();
    }
}
