package com.cf.imes.framework.organ.core.db;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.cf.imes.framework.organ.config.OrganProperties;
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.cf.imes.framework.security.core.LoginUser;
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
import com.cf.imes.module.system.enums.permission.RoleCodeEnum;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;

import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * 基于 MyBatis Plus 多组织的功能，实现 DB 层面的多组织的功能
 *
 * @author 晨丰科技
 */
public class OrganDatabaseInterceptor implements TenantLineHandler {

    private final Set<String> ignoreTables = new HashSet<>();

    public OrganDatabaseInterceptor(OrganProperties properties) {
        // 不同 DB 下，大小写的习惯不同，所以需要都添加进去
        properties.getIgnoreTables().forEach(table -> {
            ignoreTables.add(table.toLowerCase());
            ignoreTables.add(table.toUpperCase());
        });
        // 在 OracleKeyGenerator 中，生成主键时，会查询这个表，查询这个表后，会自动拼接 ORGAN_ID 导致报错
        ignoreTables.add("DUAL");
    }

    @Override
    public Expression getTenantId() {
        return new LongValue(OrganContextHolder.getRequiredOrganId());
    }

    @Override
    public String getTenantIdColumn() {
        return "organ_id";
    }

    @Override
    public boolean ignoreTable(String tableName) {
        return OrganContextHolder.isIgnore() // 情况一，全局忽略多组织
            || CollUtil.contains(ignoreTables, tableName) // 情况二，忽略多组织的表
            || isAdmin(); //情况三，忽略超级管理员
    }
    private boolean isAdmin() {
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        if(!Objects.isNull(loginUser)) {
            Boolean isSupAdmin = loginUser.getIsSupAdmin();
            return Objects.isNull(isSupAdmin)? Boolean.FALSE : isSupAdmin;
        }
        return Boolean.FALSE;
    }

}
