package ink.wgink.module.file.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import ink.wgink.common.base.DefaultBaseService;
import ink.wgink.exceptions.ParamsException;
import ink.wgink.exceptions.SearchException;
import ink.wgink.exceptions.base.SystemException;
import ink.wgink.module.file.enums.UploadTypeEnum;
import ink.wgink.module.file.pojo.dtos.FileDTO;
import ink.wgink.module.file.pojo.dtos.FileInfoDTO;
import ink.wgink.module.file.pojo.vos.FileVO;
import ink.wgink.module.file.service.IDefaultFileService;
import ink.wgink.module.file.service.IFileService;
import ink.wgink.module.file.service.IMinIoFileService;
import ink.wgink.pojo.ListPage;
import ink.wgink.pojo.pos.FilePO;
import ink.wgink.pojo.result.ErrorResult;
import ink.wgink.pojo.result.SuccessResultList;
import ink.wgink.properties.FileProperties;
import ink.wgink.util.ResourceUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

/**
 * @ClassName: FileServiceImpl
 * @Description: 文件处理
 * @Author: WangGeng
 * @Date: 2019/3/10 7:06 PM
 * @Version: 1.0
 **/
@Service
public class FileServiceImpl extends DefaultBaseService implements IFileService {

    private static final Logger LOG = LoggerFactory.getLogger(FileServiceImpl.class);
    @Autowired
    private FileProperties fileProperties;
    @Autowired
    private IDefaultFileService defaultFileService;
    @Autowired
    private IMinIoFileService minIoFileService;

    @Override
    public void remove(String ids) {
        remove(Arrays.asList(ids.split("_")));
    }

    @Override
    public void remove(List<String> ids) {
        if (fileProperties.getUseMinIo()) {
            minIoFileService.remove(ids);
        } else {
            defaultFileService.remove(ids);
        }
    }

    @Override
    public void delete(String ids) {
        delete(Arrays.asList(ids.split("_")));
    }

    @Override
    public void delete(List<String> ids) {
        Map<String, Object> params = getHashMap(2);
        params.put("fileIds", ids);

        List<FilePO> filePOs = listPO(ids);
        if (fileProperties.getUseMinIo()) {
            minIoFileService.deleteFile(filePOs);
        } else {
            defaultFileService.deleteFile(filePOs);
            defaultFileService.delete(ids);
        }
    }

    @Override
    public String uploadSingle(MultipartFile uploadFile, UploadTypeEnum uploadTypeEnum, Map<String, Object> params) throws SystemException {
        uploadFile(null, uploadFile, uploadTypeEnum, params);
        return params.get("fileId").toString();
    }

    @Override
    public String uploadSingle(String token, MultipartFile uploadFile, UploadTypeEnum uploadTypeEnum, Map<String, Object> params) throws SystemException {
        uploadFile(token, uploadFile, uploadTypeEnum, params);
        return params.get("fileId").toString();
    }

    @Override
    public String uploadSingleByUserId(String userId, MultipartFile uploadFile, UploadTypeEnum uploadTypeEnum, Map<String, Object> params) {
        uploadFileByUserId(userId, uploadFile, uploadTypeEnum, params);
        return params.get("fileId").toString();
    }

    @Override
    public FileDTO uploadSingleForFileDTO(String token, MultipartFile uploadFile, UploadTypeEnum uploadTypeEnum, Map<String, Object> params) throws SystemException {
        uploadFile(token, uploadFile, uploadTypeEnum, params);
        FileDTO fileDTO = new FileDTO();
        fileDTO.setFileId(params.get("fileId").toString());
        fileDTO.setFileName(params.get("fileName").toString());
        fileDTO.setFileUrl(params.get("fileUrl").toString());
        fileDTO.setFileType(params.get("fileType").toString());
        return fileDTO;
    }

    /**
     * 上传文件
     *
     * @param token
     * @param uploadFile
     * @param uploadTypeEnum
     * @param params
     * @throws SystemException
     */
    private void uploadFile(String token, MultipartFile uploadFile, UploadTypeEnum uploadTypeEnum, Map<String, Object> params) throws SystemException {
        if (fileProperties.getUseMinIo()) {
            minIoFileService.uploadFile(token, uploadFile, uploadTypeEnum, params);
        } else {
            defaultFileService.uploadFile(token, uploadFile, uploadTypeEnum, params);
        }
    }

    /**
     * 上传文件
     *
     * @param userId
     * @param uploadFile
     * @param uploadTypeEnum
     * @param params
     * @throws SystemException
     */
    private void uploadFileByUserId(String userId, MultipartFile uploadFile, UploadTypeEnum uploadTypeEnum, Map<String, Object> params) throws SystemException {
        if (fileProperties.getUseMinIo()) {
            minIoFileService.uploadFileByUserId(userId, uploadFile, uploadTypeEnum, params);
        } else {
            defaultFileService.uploadFileByUserId(userId, uploadFile, uploadTypeEnum, params);
        }
    }

    @Override
    public void uploadErrorExcelFileInfo(String fileName, String uploadPath, long fileSize, Map<String, Object> params) {
        defaultFileService.saveUploadFileInfo(null, fileName, uploadPath, fileName, "xls", fileSize, params);
    }

    @Override
    public String saveFileByUserId(String userId, FileVO fileVO) {
        if (fileProperties.getUseMinIo()) {
            return minIoFileService.saveFileByUserId(userId, fileVO);
        } else {
            return defaultFileService.saveFileByUserId(userId, fileVO);
        }
    }


    @Override
    public void downLoadFile(HttpServletResponse response, Map<String, Object> params) {
        downLoadFile(null, response, params);
    }

    @Override
    public void downLoadFile(HttpServletRequest request, HttpServletResponse response, Map<String, Object> params) {
        downLoadFile(request, response, params, true);
    }

    @Override
    public boolean downLoadFile(HttpServletRequest request, HttpServletResponse response, Map<String, Object> params, boolean canRange) {
        if (fileProperties.getUseMinIo()) {
            return minIoFileService.downLoadFile(request, response, params, canRange);
        } else {
            return defaultFileService.downLoadFile(request, response, params, canRange);
        }
    }

    @Override
    public JSONObject uEditor(MultipartFile file, HttpServletRequest request, Map<String, Object> params) throws SystemException, IOException {
        if (params.get(UEDITOR_ACTION) == null || StringUtils.isBlank(params.get(UEDITOR_ACTION).toString())) {
            throw new ParamsException("参数错误");
        }
        String action = params.get(UEDITOR_ACTION).toString();
        JSONObject result = null;
        if (UEDITOR_CONFIG.equals(action)) {
            result = uEditorConfig();
        }
        if (UEDITOR_UPLOAD_IMAGE.equals(action) || UEDITOR_UPLOAD_VIDEO.equals(action) || UEDITOR_UPLOAD_FILE.equals(action)) {
            result = uEditorUpload(file, request, action, params);
        }
        if (UEDITOR_LIST_IMAGE.equals(action) || UEDITOR_LIST_FILE.equals(action)) {
            result = uEditorFileList(request, action, params);
        }
        return result;
    }

    @Override
    public JSONObject wangEditorImage(MultipartFile image, UploadTypeEnum image1, Map<String, Object> params) {
        JSONObject result = new JSONObject();
        try {
            FileDTO fileDTO = uploadSingleForFileDTO(null, image, UploadTypeEnum.IMAGE, params);
            result.put("errno", 0);
            JSONArray fileArray = new JSONArray();
            fileArray.add(String.format("route/file/download/true/%s", fileDTO.getFileId()));
            result.put("data", fileArray);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            result.put("errno", ErrorResult.ErrorResultCodeEnum.FILE_ERROR.getValue());
        }
        return result;
    }

    @Override
    public FilePO getPO(Map<String, Object> params) throws SearchException {
        if (params.get("fileId") == null) {
            throw new ParamsException("fileId不能为空");
        }
        String fileId = params.get("fileId").toString();
        if (fileProperties.getUseMinIo()) {
            return minIoFileService.getPO(fileId);
        } else {
            return defaultFileService.getPO(fileId);
        }
    }

    @Override
    public String getUploadExcelErrorPath() {
        String baseUploadPath = fileProperties.getUploadPath();
        if (StringUtils.isBlank(baseUploadPath)) {
            throw new SystemException("上传路径未配置");
        }
        return defaultFileService.getUploadPath(baseUploadPath, UploadTypeEnum.ERROR_EXCEL, null);
    }

    @Override
    public List<FileDTO> list(List<String> idList) throws SearchException {
        if (fileProperties.getUseMinIo()) {
            return minIoFileService.list(idList);
        } else {
            return defaultFileService.list(idList);
        }
    }

    @Override
    public List<FilePO> listPO(List<String> idList) {
        if (fileProperties.getUseMinIo()) {
            return minIoFileService.listPO(idList);
        } else {
            return defaultFileService.listPO(idList);
        }
    }

    @Override
    public SuccessResultList<List<FileInfoDTO>> listPageInfo(ListPage page) {
        if (fileProperties.getUseMinIo()) {
            return minIoFileService.listPageInfo(page);
        } else {
            return defaultFileService.listPageInfo(page);
        }
    }

    /**
     * uEditor文件列表
     *
     * @param action
     * @param params
     * @return
     */
    private JSONObject uEditorFileList(HttpServletRequest request, String action, Map<String, Object> params) throws SearchException {
        LOG.debug("uEditor文件列表");
        int start = Integer.parseInt(params.get("start").toString());
        int pageSize = Integer.parseInt(params.get("size").toString());
        int pageNum = start / pageSize + 1;
        String downloadFile = "true";
        String fileUrl = null;
        if (UEDITOR_LIST_IMAGE.equals(action)) {
            fileUrl = "images";
        } else {
            // UEDITOR_LIST_FILE.equals(action)
            fileUrl = "files";
            downloadFile = "false";
        }
        PageHelper.startPage(pageNum, pageSize);
        List<FileDTO> listFileDTOs;
        if (fileProperties.getUseMinIo()) {
            listFileDTOs = minIoFileService.listByUrl(fileUrl);
        } else {
            listFileDTOs = defaultFileService.listByUrl(fileUrl);
        }

        PageInfo<FileDTO> pageInfo = new PageInfo<>(listFileDTOs);
        List<Map<String, String>> fileList = new ArrayList<>();
        for (FileDTO fileDTO : listFileDTOs) {
            Map<String, String> fileMap = new HashMap<>(0);
            fileMap.put("url", String.format("%s/route/file/download/%s/%s.%s", request.getContextPath(), downloadFile, fileDTO.getFileId(), fileDTO.getFileType()));
            fileList.add(fileMap);
        }
        JSONObject uEditorListResult = new JSONObject();
        uEditorListResult.put("state", "SUCCESS");
        uEditorListResult.put("start", start);
        uEditorListResult.put("total", pageInfo.getTotal());
        uEditorListResult.put("list", fileList);
        return uEditorListResult;
    }

    /**
     * uEditor上传文件
     *
     * @param file
     * @param request
     * @param action
     * @param params
     * @return
     * @throws SystemException
     */
    private JSONObject uEditorUpload(MultipartFile file, HttpServletRequest request, String action, Map<String, Object> params) throws SystemException {
        LOG.debug("UEditor上传文件");
        FileDTO fileDTO = null;
        String downloadFile = "true";
        if (UEDITOR_UPLOAD_IMAGE.equals(action)) {
            fileDTO = uploadSingleForFileDTO(null, file, UploadTypeEnum.IMAGE, params);
        } else if (UEDITOR_UPLOAD_VIDEO.equals(action)) {
            fileDTO = uploadSingleForFileDTO(null, file, UploadTypeEnum.VIDEO, params);
            downloadFile = "true";
        } else if (UEDITOR_UPLOAD_FILE.equals(action)) {
            fileDTO = uploadSingleForFileDTO(null, file, UploadTypeEnum.FILE, params);
            downloadFile = "false";
        }
        if (fileDTO == null) {
            throw new SystemException("文件上传失败");
        }
        String fileUrl = String.format("route/file/download/%s/%s.%s", downloadFile, fileDTO.getFileId(), fileDTO.getFileType());
        JSONObject fileUploadResult = new JSONObject();
        fileUploadResult.put("state", "SUCCESS");
        fileUploadResult.put("url", fileUrl);
        fileUploadResult.put("title", fileDTO.getFileName());
        fileUploadResult.put("original", fileDTO.getFileName());
        return fileUploadResult;
    }

    /**
     * 获取ueditor配置文件
     *
     * @return
     * @throws IOException
     */
    private JSONObject uEditorConfig() throws IOException {
        LOG.debug("加载UEditor配置文件");
        String uEditorConfig = ResourceUtil.inputStreamToText(ResourceUtil.getResourceInputStream("classpath:ueditorconfig.json"));
        return JSONObject.parseObject(uEditorConfig);
    }

}
