package com.artfess.base.util;

import com.artfess.base.exception.ApplicationException;
import com.artfess.base.feign.UCFeignService;
import com.artfess.base.jwt.JwtTokenHandler;
import com.fasterxml.jackson.databind.JsonNode;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;

import javax.servlet.http.HttpServletRequest;

/**
 * @Author scott
 * @Date 2019/9/23 14:12
 * @Description: 编程校验token有效性
 */
@Slf4j
public class TokenUtils {

    /**
     * 获取 request 里传递的 token
     *
     * @param request
     * @return
     */
    public static String getTokenByRequest(HttpServletRequest request) {
        String token = request.getParameter("token");
        JwtTokenHandler jwtTokenHandler = AppUtil.getBean(JwtTokenHandler.class);
        try {
            if (StringUtil.isNotEmpty(token)) {
                String username = jwtTokenHandler.getUsernameFromToken(token);
                if (username == null) {
                    throw new ApplicationException("token非法无效!");
                }
                if (!jwtTokenHandler.isTokenExpired(token)) {
                    token = jwtTokenHandler.refreshToken(token);
                }
            }

            if (token == null) {
                token = request.getHeader("X-Access-Token");
                String username = jwtTokenHandler.getUsernameFromToken(token);
                if (username == null) {
                    throw new ApplicationException("token非法无效!");
                }
            }
            if (token == null) {
                token = jwtTokenHandler.generateFeignToken();
                String username = jwtTokenHandler.getUsernameFromToken(token);
                if (username == null) {
                    throw new ApplicationException("token非法无效!");
                }
            }
        } catch (ExpiredJwtException e) {
            throw new ApplicationException("token已过期!");
        }

        return token;
    }

    /**
     * 验证Token
     */
    public static boolean verifyToken(String token) throws Exception {
        if (StringUtils.isBlank(token)) {
            throw new ApplicationException("token不能为空!");
        }
        JwtTokenHandler jwtTokenHandler = AppUtil.getBean(JwtTokenHandler.class);
        return jwtTokenHandler.validateFeignToken(token);
    }
    /**
     * 验证Token
     */
    public static boolean verifyToken(HttpServletRequest request) throws Exception {
        log.info(" -- url --" + request.getRequestURL());
        String token = getTokenByRequest(request);

        if (StringUtils.isBlank(token)) {
            throw new ApplicationException("token不能为空!");
        }
        JwtTokenHandler jwtTokenHandler = AppUtil.getBean(JwtTokenHandler.class);
        // 解密获得username，用于和数据库进行对比
        String username = jwtTokenHandler.getUsernameFromToken(token);
        if (username == null) {
            throw new ApplicationException("token非法无效!");
        }
        UCFeignService service = AppUtil.getBean(UCFeignService.class);
        JsonNode jsonNode = service.loadUserByUsername(username);

        if (jsonNode == null || jsonNode.isEmpty()) {
            throw new ApplicationException("用户不存在!");
        }

        int lockedStatus = jsonNode.get("lockedStatus").asInt();
        // 判断用户状态
        if (lockedStatus != 1) {
            throw new ApplicationException("账号已被锁定,请联系管理员!");
        }
        int status = jsonNode.get("status").asInt();
        // 判断用户状态
        if (status != 1) {
            throw new ApplicationException("账号已被禁用或离职!");
        }

        return true;
    }

    /**
     * 刷新token（保证用户在线操作不掉线）
     *
     * @param token
     * @return
     */
    public static boolean jwtTokenRefresh(String token) {
        JwtTokenHandler jwtTokenHandler = AppUtil.getBean(JwtTokenHandler.class);
        String refreshedToken = jwtTokenHandler.refreshToken(token);
        if (StringUtil.isNotEmpty(refreshedToken)) {
            return true;
        } else {
            return false;
        }
    }
}
