package com.jy.system.service.impl;

import cn.hutool.core.map.multi.RowKeyTable;
import cn.hutool.core.map.multi.Table;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.jy.framework.handler.AllPathHandler;
import com.jy.framework.model.bo.PathInfoBo;
import com.jy.framework.model.constants.CommonConstant;
import com.jy.framework.model.constants.RedisConstant;
import com.jy.framework.redis.RedisCache;
import com.jy.framework.utils.AssertUtil;
import com.jy.framework.utils.LockUtil;
import com.jy.system.dao.SysPermissionDao;
import com.jy.system.model.dto.SysPermissionSelectDto;
import com.jy.system.model.entity.SysPermission;
import com.jy.system.service.SysPermissionService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 鉴权接口 服务实现类
 * </p>
 *
 * @author
 * @since 2024-09-06
 */
@Service
public class SysPermissionServiceImpl implements SysPermissionService {

    @Resource
    private AllPathHandler allPathHandler;

    @Resource
    private SysPermissionDao sysPermissionDao;

    @Override
    public Map<String, String> get() {
        return LockUtil.cacheLock(RedisConstant.PERMISSION_KEY, () ->
                sysPermissionDao.list().stream().collect(Collectors.toMap(
                        item -> item.getMethod() + StringPool.SPACE + item.getBestMatching(),
                        SysPermission::getCode
                )));
    }

    @Override
    public List<String> getCodeList() {
        return sysPermissionDao.list().stream().map(SysPermission::getCode).toList();
    }

    @Override
    public List<SysPermission> getList(SysPermissionSelectDto dto) {
        List<SysPermission> list = sysPermissionDao.list();
        Table<String, String, SysPermission> table = new RowKeyTable<>();
        list.forEach(item -> table.put(item.getBestMatching(), item.getMethod(), item));

        List<PathInfoBo> pathInfoList = allPathHandler.getPathInfoList();

        return pathInfoList.stream()
                .flatMap(item -> item.getMethodSet().stream().map(method -> {
                    SysPermission sysPermission = table.get(item.getBestMatching(), method);
                    if (sysPermission == null) {
                        sysPermission = new SysPermission();
                        sysPermission.setMethod(method);
                        sysPermission.setBestMatching(item.getBestMatching());
                        sysPermission.setStatus(CommonConstant.DISABLE);
                    }
                    return sysPermission;
                }))
                .filter(item -> StrUtil.isBlank(dto.getMethod()) || item.getMethod().equals(dto.getMethod()))
                .filter(item -> StrUtil.isBlank(dto.getBestMatching()) || item.getBestMatching().contains(dto.getBestMatching()))
                .filter(item -> StrUtil.isBlank(dto.getCode()) || (StrUtil.isNotBlank(item.getCode()) && item.getCode().contains(dto.getCode())))
                .filter(item -> ObjectUtil.isNull(dto.getStatus()) || item.getStatus().equals(dto.getStatus()))
                .sorted(Comparator.comparing(SysPermission::getStatus))
                .toList();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(SysPermission dto) {
        boolean exists = sysPermissionDao.codeExists(dto.getId(), dto.getCode());
        AssertUtil.eqFalse(exists, "权限标识已存在");

        refreshCache();
        sysPermissionDao.saveOrUpdate(dto);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(Long id) {
        refreshCache();
        sysPermissionDao.removeById(id);
    }

    @Override
    public void refreshCache() {
        RedisCache.delete(RedisConstant.PERMISSION_KEY);
    }

}
