package cn.ey.biz.module.system.dal.redis.abac;

import cn.ey.biz.module.system.controller.admin.abac.vo.AbacVo;
import cn.ey.biz.module.system.service.abac.AbacService;
import cn.ey.biz.module.system.util.RedisUtil;
import cn.hutool.core.collection.CollUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Repository
@Slf4j
public class AbacRedisDAO {

    private final long EXPIRE_TIME = 24 * 60 * 60; // 1天

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    @Lazy
    private AbacService abacService;

    public void set(AbacVo value) {
        String key = "SYSTEM.ABAC." + value.getApp() + "." + value.getScene();
        redisUtil.lSet(key, value, EXPIRE_TIME);
    }

    public void update(AbacVo value) {
        String key = "SYSTEM.ABAC." + value.getApp() + "." + value.getScene();

        List<AbacVo> targets = get(value.getApp(), String.valueOf(value.getScene()));
        for (int i = 0; i < targets.size(); i++) {
            if (targets.get(i).getId().equals(value.getId())) {
                log.info("[ABAC] Update cache key {} with id {}", key, value.getId());
                redisUtil.lUpdateIndex(key, i, value);
                break;
            }
        }
    }

    public void refresh(String app, String scene, List<AbacVo> value) {
        String key = "SYSTEM.ABAC." + app + "." + scene;
        redisUtil.del(key);
        redisUtil.lSetAll(key, EXPIRE_TIME, value.stream()
                .map(e -> (Object) e)
                .collect(Collectors.toList()));
        log.info("[ABAC] Refresh cache Key {} by value {}", key, value.size());
    }

    public List<AbacVo> get(String app, String scene) {
        String key = "SYSTEM.ABAC." + app + "." + scene;
        List<Object> data = redisUtil.lGet(key, 0, -1);
        if (!CollUtil.isEmpty(data)) {
            return data.stream().map(item -> (AbacVo) item).collect(Collectors.toList());
        } else {
            List<AbacVo> abacVos = abacService.getAbacByAppAndScene(app, scene);
            if (CollUtil.isEmpty(abacVos)) {
                refresh(app, scene, new ArrayList<>());
                return new ArrayList<>();
            } else {
                refresh(app, scene, abacVos);
                return abacVos;
            }
        }
    }
}
