package com.pj.current.mybatis;

import cn.hutool.core.util.ReflectUtil;
import com.pj.current.dto.APPLoginUserInfo;
import com.pj.current.dto.PCLoginUserInfo;
import com.pj.current.satoken.StpAPPUserUtil;
import com.pj.current.satoken.StpUserUtil;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import org.apache.ibatis.executor.statement.RoutingStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.util.Properties;

@Slf4j
@Intercepts(
        {@Signature(method = "prepare", type = StatementHandler.class, args = {Connection.class, Integer.class})})
@Component

public class DataScopePermissionHandler implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        if (invocation.getTarget() instanceof RoutingStatementHandler) {
            //获取路由RoutingStatementHandler
            RoutingStatementHandler statementHandler = (RoutingStatementHandler) invocation.getTarget();
            //获取StatementHandler
            StatementHandler delegate = (StatementHandler) ReflectUtil.getFieldValue(statementHandler, "delegate");

            //获取sql
            BoundSql boundSql = delegate.getBoundSql();

            //获取mapper接口
            MappedStatement mappedStatement = (MappedStatement) ReflectUtil.getFieldValue(delegate, "mappedStatement");
            //获取mapper类文件
            Class<?> clazz = Class.forName(mappedStatement.getId().substring(0, mappedStatement.getId().lastIndexOf(".")));
            //获取mapper执行方法名
            int length = mappedStatement.getId().length();
            String mName = mappedStatement.getId().substring(mappedStatement.getId().lastIndexOf(".") + 1, length);

            //遍历方法
            for (Method method : clazz.getDeclaredMethods()) {
                //方法是否含有DataScope注解，如果含有注解则将数据结果过滤
                if (method.isAnnotationPresent(DataScope.class)) {
                    DataScope requiredPermission = method.getAnnotation(DataScope.class);
                    //判断是否为select语句
                    Long tradeAreaId = getTradeAreaId();
                    if (tradeAreaId == -1) {
                        break;
                    }
                    String sql = boundSql.getSql();

                    //根据用户权限拼接sql
                    String column = requiredPermission.value();
                    String checkSql = sql.toLowerCase();
                    if (checkSql.contains("select count(0) from")) {
                        if (checkSql.contains("where")) {
                            sql = sql + " and " + column + " = " + tradeAreaId;
                        } else {
                            sql = sql + " where " + column + " = " + tradeAreaId;
                        }
                    } else {
                        sql = "select * from (" + sql + " ) as p where p." + column + " = " + tradeAreaId;
                    }
                    //将sql注入boundSql
                    ReflectUtil.setFieldValue(boundSql, "sql", sql);
                    break;
                }
            }
        }
        return invocation.proceed();
    }

    private Long getTradeAreaId() {
        return StpAPPUserUtil.isLogin() ? StpAPPUserUtil.getAPPLoginInfo().getTradeAreaId() : StpAPPUserUtil.isLogin() ? StpAPPUserUtil.getAPPLoginInfo().getTradeAreaId() : 0L;

    }


    @Override
    public Object plugin(Object target) {
        return Interceptor.super.plugin(target);
    }

    @Override
    public void setProperties(Properties properties) {
        Interceptor.super.setProperties(properties);
    }
}
