package com.fzm.mall.server.front.system.service.impl;

import com.fzm.mall.server.front.config.Redis;
import com.fzm.mall.server.front.constant.MALLGlobalConfig;
import com.fzm.mall.server.front.system.service.ApiTokenService;
import com.fzm.mall.server.front.user.model.User;
import com.fzm.mall.server.front.user.service.IUserService;
import com.fzm.mall.server.front.util.UUIdUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;

/**
 * @author wulixian
 * @since 2021/5/25
 */
@Service
@Transactional
public class ApiTokenServiceImpl implements ApiTokenService {

    private static final String API_TOKEN = "api_token";

    @Autowired
    private Redis redis;

    @Autowired
    private IUserService userService;

    @Override
    public String creatApiToken(String adminId) {
        String key = MALLGlobalConfig.PJ_SUFFIX + "_" + API_TOKEN + "_" + adminId;
        String apiToken = redis.getKey(key);
        if (null == apiToken) {
            apiToken = UUIdUtil.getUUID();
            /**
             * 设置60s失效时间，避免未知错误导致的redis内存泄露
             */
            redis.setKey(key, apiToken, 60);
        }
        return apiToken;
    }

    @Override
    public void checkApiToken(HttpServletRequest request) {
        //从请求头中获取token
        String apiToken = request.getHeader("apiToken");
        User user = userService.getByToken(request.getHeader("token"));

        String adminId = user.getUid();
        if (StringUtils.isBlank(apiToken)) {
            //如果请求头token为空就从参数中获取
            apiToken = request.getParameter("apiToken");
            //如果都为空抛出参数异常的错误
            if (StringUtils.isBlank(apiToken)) {
                throw new RuntimeException("apiToken_is_null");
            }
        }
        //如果redis中不包含该token，说明token已经被删除了，抛出请求重复异常
        String key = MALLGlobalConfig.PJ_SUFFIX + "_" + API_TOKEN + "_" + adminId;
        if (null == redis.getKey(key) || !redis.getKey(key).equals(apiToken)) {
            throw new RuntimeException("repetitive_operation_fail");
        }
        //删除token
        Boolean del = redis.del(key);
        //如果删除不成功（已经被其他请求删除），抛出请求重复异常
        if (!del) {
            throw new RuntimeException("repetitive_operation_fail");
        }
    }

}
