package com.gz.scheduled;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.gz.config.MountArchiveFileConfig;
import com.gz.core.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.frameworkset.spi.annotations.Component;
import org.springframework.context.annotation.Profile;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;

import javax.annotation.Resource;
import java.io.File;
import java.util.Set;

/**
 * 扫描档案文件定时任务
 *
 * @author LiuchangLan
 * @date 2021/3/16 13:36
 */
@Slf4j
@Component
@Profile("prod")
public class ScanArchiveFileScheduled {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * @description 递归扫描文件夹 pdf、tif 文件放入队列 其他文件、空文件夹删除处理
     * @author LiuChangLan
     * @since 2021/3/23 15:52
     */
    private void sendFileToQUeue(File directory) throws InterruptedException {
        if (directory.isDirectory()) {
            // 获取文件夹下的所有文件
            File[] files = directory.listFiles();
            // 文件夹为空、非扫描根目录、文件夹不在运行 删除目录
            if (files.length == 0 && !directory.getPath().equals(MountArchiveFileConfig.SCAN_BASE_PATH)) {
                FileUtil.del(directory);
                log.info("文件夹{}为空，自动删除", directory.getPath());
            }
            for (File file : files) {
                if (file.isDirectory()) {
                    // 扫描到文件夹 递归
                    sendFileToQUeue(file);
                } else {
                    // 等待处理中 跳过 处理错误 跳过
                    if (MountArchiveFileConfig.WAIT_HANDLE_FILE.containsKey(file.getPath())) {
                        log.info("文件[{}]待处理 跳过待处理文件", file.getPath());
                        continue;
                    }
                    if (stringRedisTemplate.hasKey(String.format(MountArchiveFileConfig.ARCHIVE_FILE_MOUNT_ERROR_FOMAT, file.getName()))) {
                        log.info("文件[{}]处理错误 跳过处理错误文件", file.getPath());
                        continue;
                    }
                    // pdf 文件
                    if ("pdf".equals(FileUtil.getType(file))) {
                        MountArchiveFileConfig.WAIT_HANDLE_FILE.put(file.getPath(), file);
                        MountArchiveFileConfig.PDF_QUEUE.put(file);
                        log.info("扫描到pdf文件,当前队列还剩余{}个", MountArchiveFileConfig.PDF_QUEUE.size());
                        // tif 文件
                    } else if ("tif".equals(FileUtil.getType(file))) {
                        MountArchiveFileConfig.WAIT_HANDLE_FILE.put(file.getPath(), file);
                        MountArchiveFileConfig.TIF_QUEUE.put(file);
                        log.info("扫描到tif文件,当前队列还剩余{}个", MountArchiveFileConfig.TIF_QUEUE.size());
                    } else {
                        FileUtil.del(file);
                        log.info("扫描到其他类型文件,删除文件[{}]", file);
                    }
                }
            }
        } else {
            throw new BusinessException(500, "入参非路径");
        }
    }

    /**
     * @description 扫描根目录下的文件 进行入队
     * @author LiuChangLan
     * @since 2021/3/17 14:16
     */
    @Scheduled(cron = "0/30 * * * * ?")
    public void startScan() throws InterruptedException {
        if (Boolean.parseBoolean(stringRedisTemplate.opsForValue().get(MountArchiveFileConfig.FILE_RUNNING))){
            log.warn("文件传输中 跳过扫描");
            return;
        }
        if (StrUtil.isEmpty(MountArchiveFileConfig.SCAN_BASE_PATH)) {
            log.warn("未配置扫描根目录 跳过扫描");
            return;
        }
        log.debug("开始扫描[{}]下的档案文件", MountArchiveFileConfig.SCAN_BASE_PATH);
        File scanPath = new File(MountArchiveFileConfig.SCAN_BASE_PATH);
        if (!scanPath.exists()) {
            throw new BusinessException(500, "档案根目录不存在，无法扫描");
        }
        this.sendFileToQUeue(scanPath);
    }

    /**
     * @description 挂载错误 定时重新入队
     * @author LiuChangLan
     * @since 2021/3/17 14:15
     */
    @Scheduled(cron = "0 0 1 * * ?")
//    @Scheduled(cron = "0/30 * * * * ?")
    public void errorRejoinQueue() throws InterruptedException {
        log.debug("开始读取错误队列，重新放入队列进行挂载");
        Set<String> keys = stringRedisTemplate.keys(String.format(MountArchiveFileConfig.ARCHIVE_FILE_MOUNT_ERROR_FOMAT, "*"));
        for (String key : keys) {
            String pdfPath = stringRedisTemplate.opsForHash().get(key, MountArchiveFileConfig.ERROR_FILE_PATH_KEY).toString();
            MountArchiveFileConfig.PDF_QUEUE.put(new File(pdfPath));
            log.debug("错误文件：[{}]重新入队", pdfPath);
            stringRedisTemplate.delete(key);
        }
    }
}
