package com.gz.job;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReUtil;
import com.alibaba.fastjson.JSON;
import com.gz.config.FileUploadConfig;
import com.gz.config.MountArchiveFileConfig;
import com.gz.core.exception.BusinessException;
import com.gz.core.exception.CustomExceptionEnum;
import com.gz.dto.archive.ArchiveDTO;
import com.gz.dto.archive.SecondaryArchiveDTO;
import com.gz.dto.system.ArchiveFileDTO;
import com.gz.dto.system.ArchivesTreeDTO;
import com.gz.mapper.archive.ArchiveFileMapper;
import com.gz.mapper.archive.ArchiveMapper;
import com.gz.mapper.archive.SecondaryArchiveMapper;
import com.gz.mapper.system.ArchivesTreeMapper;
import com.gz.rvo.archive.ArchiveRVO;
import com.gz.vo.rabbitmq.OcrEtlVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.File;

/**
 * 挂挡文件
 *
 * @author LiuchangLan
 * @date 2021/3/16 13:30
 */
@Slf4j
@Component
public class MountArchiveFileJob {

    @Resource
    private ArchiveMapper archiveMapper;

    @Resource
    private SecondaryArchiveMapper secondaryArchiveMapper;

    @Resource
    private ArchivesTreeMapper archivesTreeMapper;

    @Resource
    private ArchiveFileMapper archiveFileMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Value("${upload-file.server-file-url-prefix}")
    private String serverFileUrlPrefix;

    @Value("${rabbitmq.data-exchange}")
    private String dataExchangeName;

    @Value("${rabbitmq.ocr.queue-binding-key}")
    private String ocrBindingKey;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @PostConstruct
    public void handelPDFJob() {
        log.info("[归档任务]初始化PDF文件归档任务线程");
        // 另一个线程启动 监听队列
        new Thread(() -> {
            while (true) {
                try {
                    final File pdf = MountArchiveFileConfig.PDF_QUEUE.take(); // 读取队列中信息 size为0 阻塞线程
                    log.debug("读取PDF：{},现在队列剩余：{}", pdf.getName(), MountArchiveFileConfig.PDF_QUEUE.size());
                    MountArchiveFileConfig.ARCHIVE_HANDLE_JOB_THREAD_POOL.execute(() -> {
                        String key = "";
                        try {
                            // 文件名
                            String name = pdf.getName();
                            // 文件名不带扩展名 就是档号
                            String dh = FileUtil.mainName(pdf);
                            // redisKey
                            key = String.format(MountArchiveFileConfig.ARCHIVE_FILE_MOUNT_ERROR_FOMAT, pdf.getName());
                            // 判断是否在错误队列 错误队列跳过
                            if (!stringRedisTemplate.hasKey(key)) {
                                // 案卷dto
                                ArchiveRVO archiveDTO = new ArchiveRVO();
                                // 卷内目录dto
                                SecondaryArchiveDTO secondaryArchiveDTO = new SecondaryArchiveDTO();
                                // 专业档案卷内目录 档号正则
                                if (ReUtil.isMatch(MountArchiveFileConfig.ZY_DH_RE, dh)) {
                                    secondaryArchiveDTO.setDh(dh);
                                    secondaryArchiveDTO = secondaryArchiveMapper.selectOne(secondaryArchiveDTO);
                                    archiveDTO = archiveMapper.selectByPk(secondaryArchiveDTO.getArchiveId());
                                } else {
                                    archiveDTO.setDh(dh);
                                    archiveDTO = archiveMapper.selectByDh(archiveDTO.getDh());

                                }
                                if (archiveDTO == null) {
                                    throw new BusinessException(CustomExceptionEnum.ARCHIVE_DATA_NOT_EXISTS);
                                }
                                ArchivesTreeDTO parentMl = archivesTreeMapper.selectParentByCode(archiveDTO.getMl());
                                String mlDirectory = (parentMl == null) ? archiveDTO.getMl() : parentMl.getCode() + "/" + archiveDTO.getMl();
                                String finallyPath = "/" + archiveDTO.getQzh() + "/" + archiveDTO.getGdnd() + "/" + mlDirectory + "/" + archiveDTO.getBgqx() + "/" + archiveDTO.getDh() + "/pdf/";
                                FileUtil.copy(pdf, new File(FileUploadConfig.ARCHIVE_FILE_ROOT_DIRECTORY + finallyPath + name), true);
                                log.debug("复制文件:[{}]成功", name);
                                // 删除扫描成功文件
                                if (!FileUtil.del(pdf)) {
                                    throw new BusinessException(CustomExceptionEnum.DEL_ORIGINAL_FILE_ERROR);
                                }
                                ArchiveFileDTO archiveFileDTO = new ArchiveFileDTO();
                                archiveFileDTO.setArchiveId(archiveDTO.getId());
                                if (ObjectUtil.isNotNull(secondaryArchiveDTO)) {
                                    archiveFileDTO.setSecondaryArchiveId(secondaryArchiveDTO.getId());
                                }
                                archiveFileDTO.setFileName(pdf.getName());
                                archiveFileDTO.setOriginalFileName(pdf.getName());
                                archiveFileDTO.setFileSize(FileUtil.size(pdf));
                                archiveFileDTO.setFilePath(finallyPath);
                                archiveFileDTO.setFileType(0);
                                if (archiveFileMapper.selectOne(archiveFileDTO) == null) {
                                    archiveFileMapper.insertSelective(archiveFileDTO);
                                } else {
                                    log.info("有文件记录跳过");
                                }
                                // TODO: 2021/3/17 发送rabbitmq 队列消息
                                if (ObjectUtil.isNotNull(archiveDTO)) {
                                    OcrEtlVO ocrBean = BeanUtil.copyProperties(archiveDTO, OcrEtlVO.class);
                                    ocrBean.setFileUrl(serverFileUrlPrefix + archiveFileDTO.getFilePath() + "/" + archiveFileDTO.getFileName());
                                    if (ObjectUtil.isNotNull(secondaryArchiveDTO)) {
                                        ocrBean.setSecondaryArchiveId(secondaryArchiveDTO.getId());
                                    } else {
                                        ocrBean.setSecondaryArchiveId(null);
                                    }
                                    log.info("【ocr识别】发起识别队列，参数[{}]", JSON.toJSONString(ocrBean));
                                    rabbitTemplate.convertAndSend(dataExchangeName, ocrBindingKey, JSON.toJSONString(ocrBean));
                                }
                            }
                        } catch (Exception e) {
                            log.error("挂载出现错误:", e);
                            stringRedisTemplate.opsForHash().put(key, MountArchiveFileConfig.ERROR_MSG_KEY, e.getMessage());
                            stringRedisTemplate.opsForHash().put(key, MountArchiveFileConfig.ERROR_TIME_KEY, DateUtil.now());
                            stringRedisTemplate.opsForHash().put(key, MountArchiveFileConfig.ERROR_FILE_PATH_KEY, pdf.getPath());
                        }
                        MountArchiveFileConfig.WAIT_HANDLE_FILE.remove(pdf.getPath()); // 执行完毕 移除等待处理Map
                    });
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}
