package com.mortals.xhx.base.system.upload.web;


import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.mortals.framework.annotation.UnAuth;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.web.BaseController;
import com.mortals.xhx.base.system.upload.service.UploadService;
import com.mortals.xhx.module.device.model.DeviceModuleDistributeEntity;
import com.mortals.xhx.module.device.model.DeviceModuleDistributeQuery;
import com.mortals.xhx.module.device.service.DeviceModuleDistributeService;
import com.mortals.xhx.module.product.model.ProductVersionEntity;
import com.mortals.xhx.module.product.service.ProductVersionService;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 上传文件
 *
 * @author: zxfei
 * @date: 2021/11/30 10:06
 */
@RestController
@RequestMapping("file")
public class UploadController extends BaseController {

    @Resource
    private UploadService uploadService;
    @Autowired
    private ProductVersionService productVersionService;
    @Autowired
    private DeviceModuleDistributeService deviceModuleDistributeService;


    @RequestMapping(value = "upload")
    @UnAuth
    public String doFileUpload(HttpServletRequest request, UploadForm form) {
        Map<String, Object> model = new HashMap<>();
        String jsonStr = "";
        try {
            String filePath = uploadService.saveFileUpload(form.getUploadFile(), form.getPrePath(), getCurUser());
            model.put("url", filePath);
            model.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
            jsonStr = JSONObject.toJSONString(model);
        } catch (AppException e) {
            log.debug(e);
            model.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            model.put(KEY_RESULT_MSG, e.getMessage());
            jsonStr = JSONObject.toJSONString(model);
        } catch (Exception e) {
            doException(request, "上传文件", new HashMap<>(3), e);
            model.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            model.put(KEY_RESULT_MSG, "文件上传失败");
            jsonStr = JSONObject.toJSONString(model);
        }
        return jsonStr;
    }


    @RequestMapping(value = "commonupload")
    @UnAuth
    public String doFileUpload(MultipartFile file, @RequestParam(value = "prePath", defaultValue = "file/fileupload") String prePath) {
        Map<String, Object> model = new HashMap<>();
        String jsonStr = "";
        try {
            String filePath = uploadService.saveFileUpload(file, prePath, getCurUser());
            model.put("url", filePath);
            model.put("fileName", file.getOriginalFilename());
            model.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
            jsonStr = JSONObject.toJSONString(model);
        } catch (AppException e) {
            log.debug(e);
            model.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            model.put(KEY_RESULT_MSG, e.getMessage());
            jsonStr = JSONObject.toJSONString(model);
        } catch (Exception e) {
            doException(request, "上传文件", new HashMap<>(3), e);
            model.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            model.put(KEY_RESULT_MSG, "文件上传失败");
            jsonStr = JSONObject.toJSONString(model);
        }
        return jsonStr;
    }


    /**
     * 通用下载请求
     *
     * @param fileName 文件名称
     * @param delete   是否删除
     */
    @GetMapping("common/download")
    public void fileDownload(String fileName, Boolean delete, HttpServletResponse response) {
        try {
            uploadService.fileDownload(fileName, delete, response);
        } catch (Exception e) {
            log.error("下载文件失败", e);
        }
    }

    /**
     * 图片预览 (PathVariable)
     *
     * @param fileName 文件名称
     */
    @GetMapping("preview/{fileName}")
    public void preView(@PathVariable(value = "fileName") String fileName, HttpServletResponse response) {
        try {
            uploadService.preview(fileName, response);
        } catch (Exception e) {
            log.error("下载文件失败:", e);
        }
    }

    /**
     * 通用文件下载
     *
     * @param fileName 文件名称
     */
    @GetMapping("fileupload/{fileName}")
    public void fileupload(@PathVariable(value = "fileName") String fileName, HttpServletResponse response) {
        try {
            uploadService.uploadDownload(fileName, response);
        } catch (Exception e) {
            log.error("下载文件失败:", e);
        }
    }


    /**
     * 获取所有相关资源文件并压缩打包成zip
     */
    @GetMapping(value = "zip")
    @UnAuth
    public void zip() {
        JSONObject jsonObject = new JSONObject();
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ZipOutputStream zip = new ZipOutputStream(outputStream);

            List<ProductVersionEntity> productVersionEntities = productVersionService.find(new ProductVersionEntity());
            for (ProductVersionEntity productVersionEntity : productVersionEntities) {
                String filePath = productVersionEntity.getFilePath();
                filePath = uploadService.getFilePath(filePath);
                File file = new File(filePath);
                if (file.exists()) {
                    try {
                        zip.putNextEntry(new ZipEntry(StrUtil.removePrefix(filePath, "/")));
                        IOUtils.write(FileUtil.readBytes(file), zip);
                        zip.flush();
                        zip.closeEntry();
                    } catch (Exception e) {
                        log.error("异常", e);
                    }
                }
            }

            List<DeviceModuleDistributeEntity> deviceModuleDistributeEntities = deviceModuleDistributeService.find(new DeviceModuleDistributeQuery().siteId(1L));
            for (DeviceModuleDistributeEntity deviceModuleDistributeEntity : deviceModuleDistributeEntities) {
                String filePath = deviceModuleDistributeEntity.getFilePath();
                filePath = uploadService.getFilePath(filePath);
                File file = new File(filePath);
                if (file.exists()) {
                    try {
                        zip.putNextEntry(new ZipEntry(StrUtil.removePrefix(filePath, "/")));
                        IOUtils.write(FileUtil.readBytes(file), zip);
                        zip.flush();
                        zip.closeEntry();
                    } catch (Exception e) {
                        log.error("异常", e);
                    }
                }
            }
            IOUtils.closeQuietly(zip);
            byte[] bytes = outputStream.toByteArray();
            genCode(response, bytes);

            jsonObject.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
            jsonObject.put(KEY_RESULT_MSG, "压缩文件成功！");
        } catch (Exception e) {
            log.error("获取异常", e);
            jsonObject.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
        }
    }

    /**
     * 生成zip文件
     */
    private void genCode(HttpServletResponse response, byte[] data) throws IOException {
        response.reset();
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
        response.setHeader("Content-Disposition", "attachment; filename=\"skin.zip\"");
        response.addHeader("Content-Length", "" + data.length);
        response.setContentType("application/octet-stream; charset=UTF-8");
        IOUtils.write(data, response.getOutputStream());
    }


}