package com.bcxin.sync.ascept;

import com.bcxin.sync.common.CommonConstant;
import com.bcxin.sync.common.exception.GetResponseException;
import com.bcxin.sync.common.utils.TokenUtils;
import com.bcxin.sync.entity.tenant.ExternalMembersEntity;
import com.bcxin.sync.entity.tenant.TenantEmployeesEntity;
import com.bcxin.sync.service.RedisCache;
import com.bcxin.sync.service.tenant.ExternalMembersService;
import com.bcxin.sync.service.tenant.TenantEmployeesService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * description：鉴权切面
 * author：linchunpeng
 * date：2023/11/7
 */
@Slf4j
@Component
@Aspect
public class AuthAspect {

    @Autowired
    private TenantEmployeesService tenantEmployeesService;
    @Autowired
    private ExternalMembersService externalMembersService;
    @Autowired
    private RedisCache redisCache;

    /**
     * 路径校验器
     */
    private AntPathMatcher antPathMatcher =  new AntPathMatcher();

    /**
     * description：环绕切面
     * author：linchunpeng
     * date：2023/11/15
     */
    @Around("execution(* com.bcxin.sync.controller.*.*(..))")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
        HttpServletRequest request = servletRequestAttributes.getRequest();

        if (this.isMatch(request.getRequestURI(), getPublicUris())) {
            return proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
        }
        //取出授权信息
        String accesstoken = TokenUtils.getBcxToken(request);
        if (StringUtils.isBlank(accesstoken)) {
            throw new GetResponseException(401, "访问未授权.");
        }
        String employeeId = TokenUtils.getEmployeeIdFromBcxToken(accesstoken);
        if (StringUtils.isBlank(employeeId)) {
            throw new GetResponseException(401, "访问未授权..");
        }
        String linbaoOrgId = request.getParameter("linbaoOrgId");
        String userId;
        String orgId;
        String empId;

        if ("zgU1bshE".equals(linbaoOrgId)) {
            linbaoOrgId = null;
        }

        String key = "data-sync:employee:type-id:" + employeeId;
        if (StringUtils.isNotBlank(linbaoOrgId)) {
            //如果传临保组织id，需要修改key
            key = "data-sync:employee:type-id:" + employeeId + "_" + linbaoOrgId;
        }
        Object value = redisCache.getCacheObject(key);
        if (value != null) {
            String[] typeId = value.toString().split(";");
            userId = typeId[0];
            orgId = typeId[1];
            empId = typeId[2];
        } else {
            //普通职员
            TenantEmployeesEntity employeesEntity = tenantEmployeesService.getById(employeeId);
            if (employeesEntity != null) {
                userId = employeesEntity.getTenantUserId();
                orgId = employeesEntity.getOrganizationId();
                empId = employeesEntity.getId();
            } else {
                //职员表不存在，查询团队分组成员
                ExternalMembersEntity membersEntity = externalMembersService.getById(employeeId);
                userId = membersEntity.getTenantUserId();
                orgId = membersEntity.getReferenceNumber();
                empId = membersEntity.getId();
            }
            if (StringUtils.isBlank(userId)) {
                throw new GetResponseException(404, "资源不存在");

            }
            if (StringUtils.isNotBlank(linbaoOrgId)) {
                //如果传临保组织id，需要修改职员id、组织id
                empId = userId.concat("_").concat(orgId);
                orgId = linbaoOrgId;
            }
            String typeId = userId.concat(";").concat(orgId).concat(";").concat(empId);
            redisCache.setCacheObject(key, typeId, 30, TimeUnit.MINUTES);
        }

        request.setAttribute("userId", userId);
        request.setAttribute("orgId", orgId);
        request.setAttribute("empId", empId);

        Object[] args = proceedingJoinPoint.getArgs();
        for (Object obj : args) {
            if (obj != null) {
                Class clazz = obj.getClass();
                while (clazz != null) {
                    Field[] fields = clazz.getDeclaredFields();
                    if (fields.length > 0) {
                        for (Field item : fields) {
                            if (item.getName().equals("userId")) {
                                if (userId != null) {
                                    if (item.getGenericType().toString().equals("class java.lang.String")) {
                                        item.setAccessible(true);
                                        try {
                                            item.set(obj, userId);
                                        } catch (Exception e) {
                                            e.printStackTrace();
                                        }
                                    }
                                }
                            } else if (item.getName().equals("orgId")) {
                                if (orgId != null) {
                                    if (item.getGenericType().toString().equals("class java.lang.String")) {
                                        item.setAccessible(true);
                                        try {
                                            item.set(obj, orgId);
                                        } catch (Exception e) {
                                            e.printStackTrace();
                                        }
                                    }
                                }
                            } else if (item.getName().equals("empId")) {
                                if (empId != null) {
                                    if (item.getGenericType().toString().equals("class java.lang.String")) {
                                        item.setAccessible(true);
                                        try {
                                            item.set(obj, empId);
                                        } catch (Exception e) {
                                            e.printStackTrace();
                                        }
                                    }
                                }
                            }
                        }
                    }
                    clazz = clazz.getSuperclass();
                }
            }
        }

        Object proceed = proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
//        log.info("职员id：{}，请求地址：{}，返回参数：{}", employeeId, request.getRequestURI(), JSONObject.toJSONString(proceed));
        return proceed;
    }

    /**
     * description：实付匹配
     * author：linchunpeng
     * date：2023/11/15
     */
    private boolean isMatch(String url, List<String> uris) {
        if(uris==null){
            return false;
        }
        for (String uri : uris) {
            if (this.antPathMatcher.match(uri, url)) {
                return true;
            }
        }
        return false;
    }

    /**
     * description：不需要鉴权的接口url
     * author：linchunpeng
     * date：2023/11/15
     */
    private List<String> getPublicUris() {
        return Arrays.asList("/oauth/**", "/user/**");
    }
}
