package cn.cslg.pas.service;


import cn.cslg.pas.common.utils.*;
import cn.cslg.pas.common.utils.SecurityUtils.LoginUtils;
import cn.cslg.pas.domain.Patent;
import cn.cslg.pas.domain.PatentImage;
import cn.cslg.pas.domain.PatentInstruction;
import cn.cslg.pas.domain.ProjectFile;
import cn.cslg.pas.mapper.PatentInstructionMapper;
import cn.cslg.pas.common.core.base.Constants;
import cn.cslg.pas.common.core.base.EStatus;
import cn.cslg.pas.common.model.dto.UploadFileDTO;
import cn.cslg.pas.common.model.vo.PatentInstructionVO;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ZipUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 专利说明书 服务类
 * </p>
 *
 * @author 王岩
 * @since 2022-03-02
 */
@Service
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
public class PatentInstructionService extends ServiceImpl<PatentInstructionMapper, PatentInstruction> {

    private final FileUtils fileUtils;
    private final PatentService patentService;
    private final ProjectFileService projectFileService;
    private final LoginUtils loginUtils;

    public IPage<PatentInstruction> getPageList(PatentInstructionVO params) {
        LambdaQueryWrapper<PatentInstruction> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotEmpty(params.getPatentNo())) {
            queryWrapper.like(PatentInstruction::getPatentNo, params.getPatentNo());
        }
        if (params.getType() != null) {
            queryWrapper.eq(PatentInstruction::getType, params.getType());
        }
        if (params.getPatentId() != null) {
            queryWrapper.eq(PatentInstruction::getPatentId, params.getPatentId());
        }
        IPage<PatentInstruction> pageList = this.page(new Page<>(params.getCurrent(), params.getSize()), queryWrapper);
        return pageList;
    }

    public List<PatentInstruction> getPatentInstructionByPatentNo(String patentNo) {
        LambdaQueryWrapper<PatentInstruction> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PatentInstruction::getPatentNo, patentNo);
        return this.list(queryWrapper);
    }

    public List<PatentInstruction> getPatentInstructionByPatentNo(List<String> patentNo) {
        if (patentNo == null || patentNo.size() == 0) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<PatentInstruction> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(PatentInstruction::getPatentNo, patentNo);
        return this.list(queryWrapper);
    }

    public PatentInstruction getPatentInstructionByPatentNoAndType(String patentNo, Integer type) {
        LambdaQueryWrapper<PatentInstruction> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PatentInstruction::getType, type);
        queryWrapper.eq(PatentInstruction::getPatentNo, patentNo);
        return this.getOne(queryWrapper);
    }

    @Async("singleThreadAsyncTaskExecutor")
    @Transactional(rollbackFor = Exception.class)
    public void batchUpload(String url, Integer type, String remark, Integer userId) {
        String tempPath = null;
        try {
            String tempDirectoryName = IdUtil.simpleUUID();
            tempPath = fileUtils.getSystemPath(tempDirectoryName);
            File tempDirectory = new File(tempPath);
            if (!tempDirectory.exists()) {
                tempDirectory.mkdir();
            }
            ZipUtil.unzip(fileUtils.getSystemPath(url), tempPath);
            List<File> fileList = FileUtil.loopFiles(tempPath).stream().filter(item -> FileUtil.getType(item).equals("pdf")).collect(Collectors.toList());
            for (int i = 0; i < fileList.size(); i++) {
                File file = fileList.get(i);
                String fileName = file.getName();
                String patentNo = FileUtil.getPrefix(file);
                String saveName = IdUtil.simpleUUID() + ".pdf";
                String saveUrl = fileUtils.getDirectory(saveName);
                String savePath = fileUtils.getSystemPath(saveUrl);
                FileUtil.copy(file.getPath(), savePath, true);
                PatentInstruction temp = this.getPatentInstructionByPatentNoAndType(patentNo, type);
                if (temp == null) {
                    temp = new PatentInstruction();
                } else {
                    FileUtil.del(fileUtils.getSystemPath(temp.getUrl()));
                }
                temp.setPatentNo(patentNo);
                temp.setFileName(saveName);
                temp.setSize(FileUtil.size(file));
                temp.setUrl(saveUrl);
                temp.setRemark(remark);
                temp.setCreateBy(userId);
                temp.setType(type);
                temp.insertOrUpdate();
                Map<String, Object> data = new HashMap<>();
                data.put("index", i);
                data.put("total", fileList.size());
                WebSocketServer.sendInfo(Response.websocket(data, ResponseEnum.BATCH_UPLOAD_INSTRUCTION_TASK_SUCCESS), String.valueOf(userId));
            }
        } catch (Exception e) {
            e.printStackTrace();
            WebSocketServer.sendInfo(Response.error(ResponseEnum.BATCH_UPLOAD_INSTRUCTION_TASK_ERROR), String.valueOf(userId));
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        } finally {
            FileUtil.del(tempPath);
        }
    }

    public String add(MultipartFile file, PatentInstruction patentInstruction) {
        UploadFileDTO fileDTO = fileUtils.uploadFile(file);
        patentInstruction.setCreateBy(loginUtils.getId());
        patentInstruction.setUrl(fileDTO.getPath());
        patentInstruction.setFileName(fileDTO.getFileName());
        patentInstruction.insert();
        return Response.success(patentInstruction.getId());
    }

    @Transactional
    public String edit(MultipartFile file, PatentInstruction patentInstruction) {
        this.deleteByPatentNoAndType(patentInstruction.getPatentNo(), patentInstruction.getType());
        if (StringUtils.isNotEmpty(patentInstruction.getUrl())) {
            FileUtil.del(fileUtils.getSystemPath(patentInstruction.getUrl()));
        }
        UploadFileDTO fileDTO = fileUtils.uploadFile(file);
        patentInstruction.setCreateBy(loginUtils.getId());
        patentInstruction.setUrl(fileDTO.getPath());
        patentInstruction.setFileName(fileDTO.getFileName());
        patentInstruction.setSize(fileDTO.getFileSize());
        patentInstruction.insert();
        return Response.success(true);
    }

    /**
     * 说明书pdf表数据入库
     *
     * @param patentNo
     * @param pdf
     * @return
     */
    @Transactional
    public String edit(String patentNo, UploadFileDTO pdf) {
        PatentInstruction patentInstruction = new PatentInstruction();
        patentInstruction.setUrl(pdf.getPath());
        patentInstruction.setFileName(pdf.getFileName());
        patentInstruction.setSize(pdf.getFileSize());
        patentInstruction.setPatentNo(patentNo);
        patentInstruction.setType(1);
        patentInstruction.insert();
        return Response.success(true);
    }

    public String delete(Integer id) {
        PatentInstruction temp = this.getById(id);
        this.removeById(id);
        if (StringUtils.isNotEmpty(temp.getUrl())) {
            FileUtil.del(fileUtils.getSystemPath(temp.getUrl()));
        }
        return Response.success(true);
    }

    public void deleteByPatentNoAndType(String patentNo, Integer type) {
        this.remove(Wrappers.<PatentInstruction>lambdaQuery().eq(PatentInstruction::getPatentNo, patentNo).eq(PatentInstruction::getType, type));
    }

    public void importPatentInstruction(Integer userId, String tempPath, String patentIdPatentNoJson, String patentInstructionJson) {
        List<Patent> importPatentList = JsonUtils.jsonToList(patentIdPatentNoJson, Patent.class);
        List<PatentInstruction> importPatentInstructionList = JsonUtils.jsonToList(patentInstructionJson, PatentInstruction.class);
        List<PatentInstruction> localPatentInstructionList = this.getPatentInstructionByPatentNo(importPatentList.stream().map(Patent::getPatentNo).collect(Collectors.toList()));
        for (PatentInstruction patentInstruction : importPatentInstructionList) {
            String fileName = IdUtil.simpleUUID() + "." + FileUtil.extName(patentInstruction.getFileName());
            String saveUrl = fileUtils.getDirectory(fileName);
            String savePath = fileUtils.getSystemPath(saveUrl);
            String tempInstruction = tempPath + FileUtils.FILE_SEPARATOR + Constants.PATENT_INSTRUCTION_DIRECTORY_NAME + FileUtils.FILE_SEPARATOR + patentInstruction.getFileName();
            patentInstruction.setId(null);
            patentInstruction.setFileName(fileName);
            patentInstruction.setUrl(saveUrl);
            patentInstruction.setCreateBy(userId);
            patentInstruction.setCreateTime(new Date());
            if (FileUtil.exist(tempInstruction)) {
                patentInstruction.insert();
                FileUtil.copy(tempInstruction, savePath, true);
            }
        }
        localPatentInstructionList.forEach(item -> {
            item.deleteById();
            FileUtil.del(fileUtils.getSystemPath(item.getUrl()));
        });
    }
}
