package cn.ey.biz.module.system.framework.datapermission.rule;

import cn.ey.biz.common.enums.CommonStatusEnum;
import cn.ey.biz.framework.datapermission.core.rule.DataPermissionRule;
import cn.ey.biz.framework.mybatis.core.util.MyBatisUtils;
import cn.ey.biz.framework.security.core.util.SecurityFrameworkUtils;
import cn.ey.biz.module.system.service.permission.PermissionService;
import cn.ey.biz.module.system.service.permission.RoleService;
import cn.hutool.core.collection.CollectionUtil;
import net.sf.jsqlparser.expression.Alias;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import static java.util.Collections.singleton;

@Component
public class AppDataPermissionRule implements DataPermissionRule {

    private final Map<String, String> tableNames = new HashMap<>();

    @Resource
    private PermissionService permissionService;

    @Resource
    private RoleService roleService;

    @Override
    public Set<String> getTableNames() {
        return tableNames.keySet();
    }

    @Override
    public Expression getExpression(String tableName, Alias alias) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        assert userId != null;

        // 超管有所有权限
        Set<Long> roleIds = permissionService.getUserRoleIdsFromCache(userId, singleton(CommonStatusEnum.ENABLE.getStatus()));
        if (roleService.hasAnySuperAdmin(roleIds)) {
            return null;
        }

        List<Expression> exps = permissionService.getAppsByUser().stream()
                .map(StringValue::new).collect(Collectors.toList());
        String column = tableNames.get(tableName);

        if (!StringUtils.isEmpty(column) && CollectionUtil.isNotEmpty(exps)) {
            return new InExpression(MyBatisUtils.buildColumn(tableName, alias, column), new ExpressionList(exps));
        } else {
            return null;
        }
    }

    public void setTableName(String tableName, String column) {
        this.tableNames.put(tableName, column);
    }

}
