package com.yn.bftl.thirdparty.aop;

import com.yn.bftl.common.common.constant.RedisConstant;
import com.yn.bftl.common.common.exception.YnceError;
import com.yn.bftl.thirdparty.common.enums.OperatorType;
import com.yn.bftl.thirdparty.common.exception.YnceErrorException;
import com.yn.bftl.thirdparty.common.repository.CustomerRepository;
import com.yn.bftl.thirdparty.common.repository.UserRepository;
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.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/**
 * 切面-验证User身份
 *
 * @author chendehuihuo
 * @date 2021/11/19  14:08
 */
@Slf4j
@Aspect
@Component
public class SessionAspect {

    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private UserRepository userRepository;
    @Resource
    private CustomerRepository customerRepository;

    /**
     * 用户token-登录令牌 在请求头中的名称
     */
    public static final String USER_TOKEN_HEADER_NAME = "User-Token";

    /**
     * 客户token-登录令牌 在请求头中的名称
     */
    public static final String CUSTOMER_TOKEN_HEADER_NAME = "Customer-Token";

    /**
     * 管理员token-登录令牌 在请求头中的名称
     */
    public static final String ADMIN_TOKEN_HEADER_NAME = "Admin-Token";

    /**
     * 用户ID 在请求头中的名称
     */
    public static final String USER_ID_HEADER_NAME = "User-Id";

    /**
     * 操作人token-登录令牌
     */
    public static final String OPERATOR_TOKEN = "Member-Token";

    /**
     * 操作人类型
     */
    public static final String OPERATOR_TYPE = "Operator-Type";

    @Pointcut("execution(public * com.yn.bftl.thirdparty.modules.*.controller.member.*.*(..))")
    public void anyMethod() {
    }

    /**
     * 客户未登录，直接跳过
     */
    @Pointcut("execution(public * com.yn.bftl.thirdparty.modules.*.controller.*.*(..))")
    public void anyMethodSkip() {
    }

    /**
     * 验证并返回用户信息
     *
     * @param joinPoint
     */
    @Before("anyMethod()")
    public void doAccessCheck(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String userToken = request.getHeader(USER_TOKEN_HEADER_NAME);
        String customerToken = request.getHeader(CUSTOMER_TOKEN_HEADER_NAME);
        String adminToken = request.getHeader(ADMIN_TOKEN_HEADER_NAME);
        // 用户TOKEN和客户TOKEN不允许同时传递
        if (StringUtils.isNotBlank(userToken) && StringUtils.isNotBlank(customerToken)) {
            // TODO 抛出异常
        }
        // 获取redis缓存的key值
        String redisKey = null;
        // 判断操作人类型
        OperatorType operatorType = null;
        if (StringUtils.isNotBlank(userToken)) {
            redisKey = RedisConstant.getUserTokenKey(userToken);
            operatorType = OperatorType.MEMBER_USER;
        }
        if (StringUtils.isNotBlank(customerToken)) {
            redisKey = RedisConstant.getCustomerTokenKey(customerToken);
            operatorType = OperatorType.MEMBER_CUSTOMER;
        }
        if (StringUtils.isNotBlank(adminToken)) {
            redisKey = RedisConstant.getAdminTokenKey(adminToken);
            operatorType = OperatorType.MEMBER_USER;
        }
        // 通过key值获取redis缓存的操作人ID
        String operatorId = stringRedisTemplate.opsForValue().get(redisKey);
        if (StringUtils.isBlank(operatorId)) {
            throw new YnceErrorException(YnceError.YNCE_201001);
        }
        // 获取操作人
        Object operator = null;
        if (StringUtils.isNotBlank(userToken)) {
            operator = userRepository.findById(Long.valueOf(operatorId)).orElse(null);
        }
        if (StringUtils.isNotBlank(adminToken)) {
            // 获取用户参数
            String userId = request.getHeader(USER_ID_HEADER_NAME);
            if (StringUtils.isNotBlank(userId)) {
                operator = userRepository.findById(Long.valueOf(userId)).orElse(null);
            }
        }
        if (StringUtils.isNotBlank(customerToken)) {
            operator = customerRepository.findById(Long.valueOf(customerToken)).orElse(null);
        }
        if (operator == null) {
            throw new YnceErrorException(YnceError.YNCE_201002);
        }
        request.setAttribute(OPERATOR_TOKEN, operator);
        request.setAttribute(OPERATOR_TYPE, operatorType);
    }

    /**
     * 验证并返回客户信息
     * 拦截不报错
     *
     * @param joinPoint
     */
    @Before("anyMethodSkip()")
    public void doAccessCheckSkip(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String userToken = request.getHeader(USER_TOKEN_HEADER_NAME);
        String customerToken = request.getHeader(CUSTOMER_TOKEN_HEADER_NAME);
        String adminToken = request.getHeader(ADMIN_TOKEN_HEADER_NAME);
        log.info(request.getRequestURI() + ",contentType:" + request.getHeader("content-type"));
        // 用户TOKEN和客户TOKEN不允许同时传递
        if (StringUtils.isNotBlank(userToken) && StringUtils.isNotBlank(customerToken)) {
            // TODO 抛出异常
        }
        // 获取redis缓存的key值
        String redisKey = "";
        // 判断操作人类型
        OperatorType operatorType = null;
        if (StringUtils.isNotBlank(userToken)) {
            redisKey = RedisConstant.getUserTokenKey(userToken);
            operatorType = OperatorType.MEMBER_USER;
        }
        if (StringUtils.isNotBlank(customerToken)) {
            redisKey = RedisConstant.getCustomerTokenKey(customerToken);
            operatorType = OperatorType.MEMBER_CUSTOMER;
        }
        if (StringUtils.isNotBlank(adminToken)) {
            redisKey = RedisConstant.getAdminTokenKey(adminToken);
            operatorType = OperatorType.MEMBER_USER;
        }
        if (StringUtils.isEmpty(redisKey)) {
            return;
        }
        // 通过key值获取redis缓存的操作人ID
        String operatorId = stringRedisTemplate.opsForValue().get(redisKey);
        if (StringUtils.isNotBlank(operatorId)) {
            // 获取操作人
            Object operator = null;
            if (StringUtils.isNotBlank(userToken)) {
                operator = userRepository.findById(Long.valueOf(operatorId)).orElse(null);
            }
            if (StringUtils.isNotBlank(adminToken)) {
                // 获取用户参数
                String userId = request.getHeader(USER_ID_HEADER_NAME);
                if (StringUtils.isNotBlank(userId)) {
                    operator = userRepository.findById(Long.valueOf(userId)).orElse(null);
                }
            }
            if (StringUtils.isNotBlank(customerToken)) {
                operator = customerRepository.findById(Long.valueOf(customerToken)).orElse(null);
            }
            if (operator != null) {
                request.setAttribute(OPERATOR_TOKEN, operator);
                request.setAttribute(OPERATOR_TYPE, operatorType);
            }
        }
    }
}