package com.zhgd.mybatis;

import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler;
import com.zhgd.xmgl.modules.basicdata.service.IEngineeringService;
import com.zhgd.xmgl.modules.basicdata.service.IProjectService;
import com.zhgd.xmgl.security.SecurityUser;
import com.zhgd.xmgl.security.SecurityUtil;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.*;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.expression.operators.relational.ItemsList;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.select.FromItem;
import net.sf.jsqlparser.statement.select.PlainSelect;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;

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

public class DataScopeHandler implements DataPermissionHandler {

    @Lazy
    @Autowired
    private IProjectService projectService;

    @Lazy
    @Autowired
    private IEngineeringService engineeringService;


    @Override
    public Expression getSqlSegment(Expression where, String mappedStatementId) {
        return null;
    }

    private String getEngineeringSn() {
        return "engineering_sn";
    }

    private String getProjectSn() {
        return "project_sn";
    }

    public PlainSelect getSqlSegment(PlainSelect plainSelect) {
        return dataScopeFilter(plainSelect);
    }

    private PlainSelect dataScopeFilter(PlainSelect plainSelect) {
        Expression envCondition = null;
        try {
            envCondition = CCJSqlParserUtil.parseCondExpression("1 == 1");
        } catch (JSQLParserException e) {
            throw new RuntimeException(e);
        }
        Expression where = plainSelect.getWhere();
        if (where == null) {
            plainSelect.setWhere(envCondition);
        }
        SecurityUser user = SecurityUtil.getUser();
        if (user.getAccountType() == 4) {
            if (StringUtils.isNotBlank(user.getEngineeringSn())) {
                equalsTo(getAliasColumn(plainSelect, getEngineeringSn()), user.getEngineeringSn(), plainSelect);
            } else {
                equalsTo(getAliasColumn(plainSelect, getProjectSn()), user.getSn(), plainSelect);
                if (!plainSelect.getFromItem().toString().equals("engineering")) {
                    equalsTo(getAliasColumn(plainSelect, getEngineeringSn()), "", plainSelect);
                }
            }
        }
        if (user.getAccountType() == 3) {
            List<String> engineeringSns = engineeringService.getSnListByEnterprise(user.getSn());
            if (engineeringSns.size() == 0) {
                engineeringSns.add("0");
            }
            inExpression(getAliasColumn(plainSelect, getEngineeringSn()), engineeringSns, plainSelect);
        }
        if (user.getAccountType() == 2) {
            List<String> projectSns = projectService.getSnListForGov(user.getSn());
            if (projectSns.size() == 0) {
                projectSns.add("0");
            }
            inExpression(getAliasColumn(plainSelect, getProjectSn()), projectSns, plainSelect);
        }
        return plainSelect;
    }

    private void equalsTo(String leftExpression, String rightExpression, PlainSelect plainSelect) {
        EqualsTo equalsTo = new EqualsTo();
        equalsTo.setLeftExpression(new Column(leftExpression));
        equalsTo.setRightExpression(new StringValue(rightExpression));
        AndExpression andExpression = new AndExpression(plainSelect.getWhere(), equalsTo);
        plainSelect.setWhere(andExpression);
    }

    private void inExpression(String leftExpression, List<String> rightExpression, PlainSelect plainSelect) {
        InExpression inExpression = new InExpression();
        ItemsList itemsList = new ExpressionList(rightExpression.stream().map(StringValue::new).collect(Collectors.toList()));
        inExpression.setLeftExpression(new Column(leftExpression));
        inExpression.setRightItemsList(itemsList);
        AndExpression andExpression = new AndExpression(plainSelect.getWhere(), inExpression);
        plainSelect.setWhere(andExpression);
    }

    private String getAliasColumn(PlainSelect plainSelect, String sn) {
        FromItem fromItem = plainSelect.getFromItem();
        Alias alias = fromItem.getAlias();
        StringBuilder prefix = new StringBuilder();
        if (alias != null) {
            prefix.append(alias).append(".");
        }
        return prefix.append(sn).toString();
    }
}
