package org.jeecg.modules.wps.service.impl;

import cn.com.ctop.common.module.entity.Project;
import cn.com.ctop.common.module.entity.SysUser;
import cn.com.ctop.common.module.file.FileUtil;
import cn.com.ctop.common.module.service.IProjectService;
import cn.com.ctop.common.module.service.ISysUserService;
import cn.com.ctop.common.module.utils.CosUtils;
import cn.com.ctop.common.module.utils.ResultMapUtils;
import cn.com.ctop.common.module.utils.StatusCode;
import cn.com.ctop.common.module.vo.ResFileDTO;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.orderplatform.entity.PlatformScript;
import org.jeecg.modules.orderplatform.service.IPlatformScriptService;
import org.jeecg.modules.wps.config.Context;
import org.jeecg.modules.wps.dto.*;
import org.jeecg.modules.wps.entity.WpsFile;
import org.jeecg.modules.wps.entity.WpsFileVersion;
import org.jeecg.modules.wps.entity.WpsFileWatermark;
import org.jeecg.modules.wps.entity.WpsUser;
import org.jeecg.modules.wps.mapper.WpsFileMapper;
import org.jeecg.modules.wps.service.*;
import org.jeecg.modules.wps.util.Token;
import org.jeecg.modules.wps.util.WpsUtil;
import org.jeecg.modules.wps.util.upload.oss.WpsOSSUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;

/**
 * wps文件
 * @author jeecg-boot
 * @date   2020-06-01
 * @version V1.0
 */
@Slf4j
@Service
public class WpsFileServiceImpl extends ServiceImpl<WpsFileMapper, WpsFile> implements IWpsFileService {
    @Autowired
    private IWpsUserAclService wpsUserAclService;
    @Autowired
    private IWpsFileWatermarkService wpsFileWatermarkService;
    @Autowired
    private IWpsFileVersionService wpsFileVersionService;
    @Autowired
    private IWpsUserService wpsUserService;
    @Autowired
    private WpsUtil wpsUtil;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private IPlatformScriptService platformScriptService;

    private static final String OSS_URL_PREFIX = "https://ctop-media.oss-cn-beijing.aliyuncs.com/script-lib/wps/";
    @Override
    public Token getViewUrl(String fileUrl, boolean checkToken){
        Token t = new Token();

        String fileType = FileUtil.getFileTypeByPath(fileUrl);
        // fileId使用uuid保证出现同样的文件而是最新文件
        UUID randomUUID = UUID.randomUUID();
        String uuid = randomUUID.toString().replace("-","");

        Map<String,String> values = new HashMap<String,String>(){
            {
                put("_w_appid", WpsUtil.appid);
                if (checkToken){
                    put("_w_tokentype","1");
                }
                put("_w_userid", "-1");
                put("_w_filepath",fileUrl);
                put("_w_filetype","web");
            }
        };

        String wpsUrl = wpsUtil.getWpsUrl(values,fileType,uuid);

        t.setToken(uuid);
        t.setExpires_in(600);
        t.setWpsUrl(wpsUrl);

        return t;
    }

    @Override
    public Token getViewUrl(String fileId,String userId,boolean checkToken){
        WpsFile fileEntity = this.getById(fileId);
        if (fileEntity != null){
            Token t = new Token();
            String fileName = fileEntity.getName();
            String fileType = FileUtil.getFileTypeByName(fileName);

            UUID randomUuid = UUID.randomUUID();
            String uuid = randomUuid.toString().replace("-","");

            Map<String,String> values = new HashMap<>();
            values.put("_w_appid", WpsUtil.appid);
            if (checkToken){
                values.put("_w_tokentype","1");
            }
            values.put("_w_filepath",fileName);
            values.put("_w_userid", userId);
            values.put("_w_filetype","db");

            String wpsUrl = wpsUtil.getWpsUrl(values,fileType,fileEntity.getId());
            t.setToken(uuid);
            t.setExpires_in(600);
            t.setWpsUrl(wpsUrl);

            return t;
        }
        return null;
    }

    @Override
    public Token getPlatformScriptViewUrl(String fileId, String userId, boolean checkToken) {
        PlatformScript fileEntity = platformScriptService.getById(fileId);
        if (fileEntity != null){
            Token t = new Token();
            String fileName = fileEntity.getName();
            String fileType = FileUtil.getFileTypeByName(fileName);

            UUID randomUuid = UUID.randomUUID();
            String uuid = randomUuid.toString().replace("-","");

            Map<String,String> values = new HashMap<>();
            values.put("_w_appid", WpsUtil.appid);
            if (checkToken){
                values.put("_w_tokentype","1");
            }
            values.put("_w_filepath",fileName);
            values.put("_w_userid", userId);
            values.put("_w_filetype","db");

            String wpsUrl = wpsUtil.getWpsUrl(values,fileType,fileEntity.getId());
            t.setToken(uuid);
            t.setExpires_in(600);
            t.setWpsUrl(wpsUrl);

            return t;
        }
        return null;
    }

    @Override
    public Map<String,Object> getFileInfo(String userId, String filePath,String fileType,String fileId){
        if ("web".equalsIgnoreCase(fileType)){
            return getWebFileInfo(filePath);
        }else if ("db".equalsIgnoreCase(fileType)){
            return getDbFileInfo(userId,fileId);
        }
        return null;
    }

    private Map<String,Object> getWebFileInfo(String filePath){
        Map<String,Object>result = new HashMap<>();
        log.info("_w_filepath:{}",filePath);
        // 构建默认user信息
        UserDTO wpsUser = new UserDTO(
                "-1","我","read","https://zmfiletest.oss-cn-hangzhou.aliyuncs.com/user0.png"
        );

        // 构建文件
        FileDTO file = new FileDTO(
                Context.getFileId(), FileUtil.getFileName(filePath),
                1,2835,"-1",System.currentTimeMillis(), filePath,
                // 默认设置为无水印，只读权限
                new UserAclBO(),new WatermarkBO()
        );
        result.put("file",file);
        result.put("user",wpsUser);
        return result;
    }

    private Map<String,Object> getDbFileInfo(String userId,String fileId){
        log.info("获取dbfileInfo");
        Map<String,Object>result = new HashMap<>();
        WpsFile fileEntity = this.getById(fileId);
        String permission = "write";

        UserAclBO userAcl = new UserAclBO();
        // 增加水印
        WpsFileWatermark watermarkEntity = wpsFileWatermarkService.findFirstByFileId(fileId);
        WatermarkBO watermark = new WatermarkBO();
        if (watermarkEntity != null){
            BeanUtils.copyProperties(watermarkEntity,watermark);
        }
        //获取user
        SysUser loginUser = sysUserService.getById(userId);
        UserDTO user = new UserDTO();
        if (loginUser != null){
            user.setId(loginUser.getId());
            user.setName(loginUser.getRealname());
            user.setPermission(permission);
        }

        // 构建fileInfo
        FileDTO file = new FileDTO();
        BeanUtils.copyProperties(fileEntity,file);
        String url = fileEntity.getDownloadUrl();
        file.setDownload_url(url);
        file.setUser_acl(userAcl);
        file.setWatermark(watermark);
        result.put("file",file);
        result.put("user",user);
        return result;
    }

    @Override
    public void fileRename(String fileName, String userId,String fileId){
        WpsFile file = this.getById(fileId);
        if (file != null){
            file.setName(fileName);
            file.setModifier(userId);
            Date date = new Date();
            file.setModifyTime(date.getTime());
            this.updateById(file);
        }
    }

    @Override
    public Map<String,Object> fileNew(MultipartFile file, String userId){
        ResFileDTO resFileDTO = WpsOSSUtil.uploadMultipartFile(file);

        String fileName = resFileDTO.getFileName();
        String fileUrl = resFileDTO.getFileUrl();
        int fileSize = (int) file.getSize();
        Date date = new Date();
        long dataTime = date.getTime();
        // 保存文件
        WpsFile f = new WpsFile(fileName,1,fileSize,userId,userId,dataTime,dataTime,fileUrl);
        this.save(f);
        // 处理权限
        wpsUserAclService.saveUserFileAcl(userId,f.getId());
        // 处理水印
        wpsFileWatermarkService.saveWatermark(f.getId());
        // 处理返回
        Map<String,Object> map = new HashMap<>();
        map.put("redirect_url",this.getViewUrl(f.getId(),userId,false).getWpsUrl());
        map.put("user_id",userId);
        return map;
    }

    @Override
    public Map<String,Object> fileHistory(FileReqDTO req){
        Map<String,Object> map = new HashMap<>();
        List<FileHisDTO> result = new ArrayList<>(12);
        if (req.getId() == null){
            map.put("histories",result);
            return map;
        }
        // 目前先实现获取所有的历史记录
        List<WpsFileVersion> versionList = wpsFileVersionService.findByFileIdOrderByVersionDesc(req.getId());
        if (versionList == null || versionList.isEmpty()){
            map.put("histories",result);
            return map;
        }
        Set<String> userIdSet = new HashSet<>();
        for (WpsFileVersion fileVersion : versionList){
            userIdSet.add(fileVersion.getModifier());
            userIdSet.add(fileVersion.getCreator());
        }
        List<String> userIdList = new ArrayList<>(userIdSet);
        // 获取所有关联的人
        List<WpsUser> userList = wpsUserService.findByIdIn(userIdList);
        if (userList == null || userList.isEmpty()){
            map.put("histories",result);
            return map;
        }
        for (WpsFileVersion fileVersion : versionList){
            FileHisDTO fileHis = new FileHisDTO();
            BeanUtils.copyProperties(fileVersion,fileHis);
            fileHis.setId(fileVersion.getFileId());
            UserDTO creator = new UserDTO();
            UserDTO modifier = new UserDTO();
            for (WpsUser user : userList){
                if (user.getId().equals(fileVersion.getCreator())){
                    BeanUtils.copyProperties(user,creator);
                }
                if (user.getId().equals(fileVersion.getModifier())){
                    BeanUtils.copyProperties(user,modifier);
                }
            }
            fileHis.setModifier(modifier);
            fileHis.setCreator(creator);
            result.add(fileHis);
        }
        map.put("histories",result);
        return map;
    }

    @Override
    public Map<String,Object> fileSave(MultipartFile mFile,String userId,String fileId){
        Date date = new Date();
        // 上传
        ResFileDTO resFileDTO = CosUtils.uploadMultipartFile(mFile,"script-lib/wps/");
        int size = (int) resFileDTO.getFileSize();
        WpsFile file = this.getById(fileId);
        FileDTO fileInfo = new FileDTO();

        String oldFileUrl = file.getDownloadUrl();

        // 更新当前版本
        file.setVersion(file.getVersion() + 1);
        file.setDownloadUrl(resFileDTO.getFileUrl());
        file.setModifier(userId);
        file.setModifyTime(date.getTime());
        file.setSize(size);
        this.updateById(file);

        // 保存历史版本
        WpsFileVersion fileVersion = new WpsFileVersion();
        BeanUtils.copyProperties(file,fileVersion);
        fileVersion.setFileId(fileId);
        fileVersion.setVersion(file.getVersion() - 1);
        fileVersion.setDownloadUrl(oldFileUrl);
        fileVersion.setSize(size);
        wpsFileVersionService.save(fileVersion);

        // 返回当前版本信息
        BeanUtils.copyProperties(file,fileInfo);

        Map<String,Object> map = new HashMap<>();
        map.put("file",fileInfo);
        return map;
    }


    @Override
    public Map<String,Object> fileVersion(Integer version){
        FileDTO fileInfo = new FileDTO();
        String fileId = Context.getFileId();
        WpsFileVersion fileVersion =
                wpsFileVersionService.findByFileIdAndVersion(fileId,version);
        if (fileVersion != null){
            BeanUtils.copyProperties(fileVersion,fileInfo);
            fileInfo.setId(fileVersion.getFileId());
        }
        Map<String,Object> map = new HashMap<>();
        map.put("file",fileInfo);
        return map;
    }
    @Autowired
    private WpsFileMapper wpsFileMapper;

    @Override
    public List<FileListDTO> getFileList(){
        return wpsFileMapper.findAllFile();
    }
    @Override
    public Map<String,Object> getFileListByPage(int pageNum, int pageSize){
        Map<String,Object>result = new HashMap<>();
        PageHelper.startPage(pageNum,pageSize);
        List<FileListDTO> fileListDTOS = wpsFileMapper.getAllFileByPage();
        PageInfo<FileListDTO> pageInfo = new PageInfo<>(fileListDTOS);
        result.put("data",pageInfo);
        ResultMapUtils.setResultMap(result, StatusCode.COMMON_SUCCESS);
        return result;
    }

    @Override
    public int delFile(String id){
        WpsFile file = this.getById(id);
        if (file != null){
            if ("Y".equalsIgnoreCase(file.getCanDelete())){
                // del
                this.removeById(id);
                return 1;
            }else {
                return 0;
            }
        }else {
            return -1;
        }
    }

    @Override
    public WpsFile uploadFile(MultipartFile file,String userId){
        ResFileDTO resFileDTO = CosUtils.uploadMultipartFile(file,"script-lib/wps/");
        // 上传成功后，处理数据库记录值
        Date date = new Date();
        long dataTime = date.getTime();
        // 保存文件
        WpsFile f = new WpsFile(resFileDTO.getFileName(),1,((int) resFileDTO.getFileSize()),
                userId,userId,dataTime,dataTime, resFileDTO.getFileUrl());
        this.save(f);

        // 处理权限
        wpsUserAclService.saveUserFileAcl(userId,f.getId());

        // 处理水印
        wpsFileWatermarkService.saveWatermark(f.getId());

        return f;
    }
    @Override
    public String createTemplateFile(String template){
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        boolean typeTrue = FileUtil.checkCode(template);
        if (typeTrue){
            return wpsUtil.getTemplateWpsUrl(template,sysUser.getId());
        }
        return "";
    }
    @Autowired
    private IProjectService projectService;
    @Override
    public Map<String, Object> bindProject(String fileId, Long projectId) {
        Map<String,Object> result = new HashMap<>();
        WpsFile wpsFile = this.getById(fileId);
        if(null == wpsFile){
            ResultMapUtils.setResultMap(result,StatusCode.CTOP_SCRIPT_FILE_NOT_EXIST);
            return result;
        }
        Project project = projectService.getById(projectId);
        if(null == project){
            ResultMapUtils.setResultMap(result,StatusCode.CTOP_PROJECT_NOT_EXIST);
            return result;
        }
        wpsFile.setProjectId(projectId);
        this.updateById(wpsFile);
        ResultMapUtils.setResultMap(result,StatusCode.COMMON_SUCCESS);
        return result;
    }


}
