package com.fdkankan.ucenter.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fdkankan.common.constant.CommonStatus;
import com.fdkankan.common.util.DateUtil;
import com.fdkankan.common.util.FileUtils;
import com.fdkankan.redis.constant.RedisKey;
import com.fdkankan.redis.constant.RedisLockKey;
import com.fdkankan.redis.util.RedisLockUtil;
import com.fdkankan.ucenter.bean.SceneBean;
import com.fdkankan.ucenter.bean.SceneClean;
import com.fdkankan.ucenter.mapper.ISceneCleanMapper;
import com.fdkankan.ucenter.service.ISceneCleanService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 
 * @since 2022-10-09
 */
@RefreshScope
@Service
@Slf4j
public class SceneCleanServiceImpl extends ServiceImpl<ISceneCleanMapper, SceneClean> implements ISceneCleanService {

    @Autowired
    private RedisLockUtil redisLockUtil;

    @Value("${scene.clean.size:10}")
    private Integer sceneCleanSize;

    @Transactional
    @Override
    public void sceneCleanResource(){
        // 获取redis 锁
        boolean lock = redisLockUtil.lock(RedisLockKey.LOCK_SCENE_CLEAN, RedisKey.EXPIRE_TIME_2_HOUR);
        if(!lock){
            log.warn("未获取到清除资源锁，退出任务！");
            return;
        }

        Date time = DateUtil.delay(Calendar.getInstance().getTime(), -7, Calendar.MONTH);
        time.setHours(0);
        time.setMinutes(0);
        time.setSeconds(0);

        //查询需要清理资源的场景
        List<SceneBean> sceneProEntityList = selectNeadCleanScene(0,sceneCleanSize, time);
        //如果查出来的场景集合是空，证明已经没有场景资源需要删除，则需要把查询下表删除，等待下一次定时任务执行
        if (CollectionUtils.isEmpty(sceneProEntityList)) {
            log.info("未查询到过期场景，退出任务！");
            redisLockUtil.unlockLua(RedisLockKey.LOCK_SCENE_CLEAN);
            return;
        }
        List<String> numList = sceneProEntityList.parallelStream().map(SceneBean::getNum).collect(Collectors.toList());
        List<SceneClean> insertList = new ArrayList<>();
        List<SceneClean> updateList = this.list(new LambdaQueryWrapper<SceneClean>().in(SceneClean::getNum, numList));
        Set<String> updateSet = updateList.stream().map(SceneClean::getNum).collect(Collectors.toSet());
        sceneProEntityList.stream().forEach(scene -> {
            if (StringUtils.isNotBlank(scene.getDataSource())) {
                // 查询该资源的最新计算时间
                List<SceneClean> scenes = findAllByDateSource(scene.getDataSource());
                if (scenes.get(0).getCreateTime().before(time)) {
                    try {
                        FileUtils.deleteDirectory(scene.getDataSource());
                    } catch (Exception e) {
                        e.printStackTrace();
                        updateSet.remove(scene.getNum());
                        return;
                    }
                }
            }
            if (!updateSet.contains(scene.getNum())) {
                SceneClean sceneCleanEntity = new SceneClean();
                sceneCleanEntity.setState(1);
                sceneCleanEntity.setNum(scene.getNum());
                sceneCleanEntity.setCreateTime(new Date());
                sceneCleanEntity.setUpdateTime(new Date());
                sceneCleanEntity.setRecStatus("A");
                insertList.add(sceneCleanEntity);
            }
        });

        //写库
        if(!CollectionUtils.isEmpty(insertList)){
            insertList.parallelStream().forEach(insert -> log.info("清除资源目录:{}", insert.getNum()));
            this.saveBatch(insertList);
        }
        if(!CollectionUtils.isEmpty(updateSet)){
            updateSet.parallelStream().forEach(num -> log.info("清除更新资源目录:{}", num));
            this.update(new LambdaUpdateWrapper<SceneClean>()
                    .set(SceneClean::getState, CommonStatus.YES.code())
                    .set(SceneClean::getUpdateTime,new Date())
                    .in(SceneClean::getNum, updateSet));
        }

        redisLockUtil.unlockLua(RedisLockKey.LOCK_SCENE_CLEAN);
    }

    private List<SceneClean> findAllByDateSource(String dataSource) {
        return this.baseMapper.findAllByDateSource(dataSource);
    }

    @Override
    public List<SceneBean> selectNeadCleanScene(long index, int size, Date time) {
        return this.baseMapper.selectNeadCleanScene(index, size, time);
    }
}
