package com.patzn.lims.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.patzn.lims.core.api.PtAssert;
import com.patzn.lims.core.oss.OssClient;
import com.patzn.lims.core.oss.OssFileResult;
import com.patzn.lims.core.web.Account;
import com.patzn.lims.core.web.BaseServiceImpl;
import com.patzn.lims.sys.entity.SysFile;
import com.patzn.lims.sys.entity.SysFileHis;
import com.patzn.lims.sys.enums.FolderAuthorizeEnum;
import com.patzn.lims.sys.mapper.SysFileMapper;
import com.patzn.lims.sys.service.ISysFileHisService;
import com.patzn.lims.sys.service.ISysFileService;
import com.patzn.lims.sys.service.ISysRoleRelFileFolderService;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.util.List;

import static java.util.stream.Collectors.toList;

/**
 * <p>
 * 文件表 服务实现类
 * </p>
 *
 * @author patzn
 * @since 2017-10-30
 */
@Service
public class SysFileServiceImpl extends BaseServiceImpl<SysFileMapper, SysFile> implements ISysFileService {
    @Autowired
    private OssClient ossClient;
    @Autowired
    private ISysFileHisService sysFileHisService;
    @Autowired
    private ISysRoleRelFileFolderService sysRoleRelFileFolderService;

    @Override
    public Page<SysFile> page(Page<SysFile> page, SysFile sysFile) {
        return page(page, getWrapper(sysFile));
    }

    @Override
    public List<SysFile> list(SysFile sysFile) {
        return list(getWrapper(sysFile));
    }

    @Override
    public List<SysFileHis> listHis(Long fileId) {
        return sysFileHisService.list(Wrappers.<SysFileHis>query().eq("file_id", fileId));
    }

    private QueryWrapper getWrapper(SysFile sysFile) {
        QueryWrapper wrapper = new QueryWrapper(sysFile);
        wrapper.select("id,num,name,type,realname,share,object_key,version_id,ctime");
        wrapper.orderByDesc("sort");
        return wrapper;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean save(Account account, MultipartFile file, SysFile sysFile) {
        // 如果存在文件 ID 执行签入逻辑
        String fileId = null;
        if (null != sysFile.getId()) {
            SysFile oldFile = super.getById(sysFile.getId());
            if (null != oldFile) {
                fileId = oldFile.getObjectKey();
                sysFile = oldFile;
            }
        }
        /*
        if (null == sysFile.getFolderId() || !sysRoleRelFileFolderService.getUserAuthorize(account, sysFile.getFolderId(), FolderAuthorizeEnum.UPLOAD)) {
            RestAssert.fail("抱歉！您无该文件夹文件上传权限");
        }
         */
        OssFileResult ossFileResult = ossClient.upload(file);
        if (null == ossFileResult) {
            return false;
        }
        boolean result;
        // 文件类型，版本信息
        sysFile.setType(ossFileResult.getType());
        sysFile.setName(ossFileResult.getName());
        sysFile.setBucketName(ossFileResult.getBucketName());
        sysFile.setObjectKey(ossFileResult.getObjectKey());
        sysFile.setVersionId(ossFileResult.getVersionId());
        if (null != fileId) {
            // 执行签入逻辑
            result = super.updateById(sysFile);
        } else {
            // 上传新文件
            result = super.save(sysFile);
        }
        if (result) {
            // 记录历史
            return sysFileHisService.save(sysFile);
        }
        return false;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean removeByIds(Account account, Long[] ids) {
        if (null == ids || ids.length < 1) {
            return false;
        }
        Wrapper wrapper = Wrappers.<SysFile>query().in("id", ids);
        List<SysFile> sysFileList = super.list(wrapper);
        if (CollectionUtils.isEmpty(sysFileList)) {
            return false;
        }
        SysFile sysFile = sysFileList.get(0);
        if (null == sysFile || !sysRoleRelFileFolderService.getUserAuthorize(account, sysFile.getFolderId(), FolderAuthorizeEnum.REMOVE)) {
            PtAssert.fail("抱歉！您无该文件夹删除权限");
        }
        ossClient.deleteObjects(sysFileList.stream().map(e -> e.getObjectKey()).collect(toList()));
        // 删除历史移除文件
        if (sysFileHisService.removeByFileIds(ids)) {
            return super.remove(wrapper);
        }
        return false;
    }

    @Override
    public boolean checkOutFileHis(Long fileHisId) {
        SysFileHis sysFileHis = sysFileHisService.getById(fileHisId);
        if (null != sysFileHis) {
            SysFile sysFile = sysFileHis.convert(SysFile.class);
            sysFile.setId(sysFileHis.getFileId());
            return super.updateById(sysFile);
        }
        return false;
    }

    @Override
    public void download(HttpServletResponse response, Long fileId, boolean history) {
        if (history) {
            SysFileHis sysFileHis = sysFileHisService.getById(fileId);
            if (null != sysFileHis) {
                ossClient.download(sysFileHis.getObjectKey(), response);
            }
        }
        SysFile sysFile = super.getById(fileId);
        if (null != sysFile) {
            ossClient.download(sysFile.getObjectKey(), sysFile.getName() +
                    "." + sysFile.getType(), response);
        }
    }

    @Override
    public int countByFolderId(Serializable folderId) {
        return baseMapper.selectCount(Wrappers.<SysFile>query().eq("folder_id", folderId));
    }

    @Override
    public List<Integer> getAuthorize(Account account, Long id) {
        SysFile sysFile = baseMapper.selectById(id);
        if (null == sysFile) {
            // 不存在返回 null
            return null;
        }
        return sysRoleRelFileFolderService.getAuthorizeByFolderId(account, sysFile.getFolderId());
    }
}
