package com.ningdatech.carapi.datascope.aop;

import cn.hutool.core.collection.CollUtil;
import com.ningdatech.carapi.datascope.model.DataScopeDto;
import com.ningdatech.carapi.datascope.provider.DataScopeContext;
import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails;
import com.ningdatech.carapi.user.util.LoginUserUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

;

/**
 * @program:
 * @description: xml sql方式
 * 数据权限切面
 * @author: PoffyZhang
 * @created: 2022/11/11 09:12
 */
@Aspect
@Component
@Slf4j
@AllArgsConstructor
@Order(10)
public class XmlDataScopeAspect {

    @Pointcut("@annotation(com.ningdatech.carapi.datascope.aop.XmlDataScope)")
    public void xmlDataScopeAspect() {

    }

    @Before("xmlDataScopeAspect() && @annotation(xmlDataScope)")
    public void before(JoinPoint joinPoint, XmlDataScope xmlDataScope) throws Throwable {
        Optional<DataScopeDto> currentUserDataScoper = getCurrentUserDataScoper();
        if(!currentUserDataScoper.isPresent()){
            return;
        }
        DataScopeDto dataScopeDto = currentUserDataScoper.get();
        Object entity =  joinPoint.getArgs()[xmlDataScope.entityIndex()];

        if(Objects.isNull(entity)){
            return;
        }

        StringBuilder sql = new StringBuilder();
        if(CollUtil.isEmpty(dataScopeDto.getCompanyIds())
                && CollUtil.isEmpty(dataScopeDto.getRegionIds())){
            return;
        }

        if(CollUtil.isNotEmpty(dataScopeDto.getCompanyIds())){
            sql.append(" AND " + xmlDataScope.companyAlias() + ".id in ("
                     + convertForStr(dataScopeDto.getCompanyIds()) + ")");
        }


        if(CollUtil.isNotEmpty(dataScopeDto.getRegionIds())){
            sql.append(" AND " + xmlDataScope.regionAlias() + ".id in ("
                    + convertForStr(dataScopeDto.getRegionIds()) + ")");
        }

        if(sql.length() > 0){
            Class<?> clazz = entity.getClass();
            Field dataScopeSql = clazz.getDeclaredField("dataScopeSql");
            dataScopeSql.setAccessible(true);
            dataScopeSql.set(entity, sql.toString());
        }
    }

    private String convertForStr(List<Long> companyIds) {
        if(CollUtil.isEmpty(companyIds)){
            return StringUtils.EMPTY;
        }
        StringBuilder sql = new StringBuilder();
        for(Long companyId : companyIds){
            sql.append(companyId + ",");
        }
        sql.delete(sql.length()-1,sql.length());
        return sql.toString();
    }

    public Optional<DataScopeDto> getCurrentUserDataScoper(){
        UserInfoDetails loginUser = LoginUserUtil.loginUserDetail();
        if(Objects.isNull(loginUser) || Objects.isNull(loginUser.getDataScope())){
            return Optional.empty();
        }
        return DataScopeContext.getDataScope(loginUser.getDataScope());
    }
}