package thyyxxk.webserver.utils;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import thyyxxk.webserver.config.exception.BizException;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.service.hutoolcache.UserCache;

import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @author dj
 */
@Component
public class TokenUtil {
    private static final String PRIVATE_KEY = "w2XS014bk6Ma7tYh";
    private static final UserCache USER_CACHE = SpringUtil.getBean(UserCache.class);

    private TokenUtil() {
    }

    private static volatile TokenUtil INSTANCE = null;

    public static TokenUtil getInstance() {
        if (null == INSTANCE) {
            synchronized (TokenUtil.class) {
                if (null == INSTANCE) {
                    INSTANCE = new TokenUtil();
                }
            }
        }
        return INSTANCE;
    }

    public String createToken(String code, String pwd) {
        Map<String, Object> map = new HashMap<>();
        map.put("code", code);
        map.put("expire_time", System.currentTimeMillis() + 60 * 60 * 1000 * 240);
        map.put("companyLogo", "thyyxxkzy");
        return JWTUtil.createToken(map, PRIVATE_KEY.getBytes(StandardCharsets.UTF_8));
    }

    public void verifyToken(String token) {
        final JWT jwt = JWTUtil.parseToken(token);
        long expire_time = Convert.toLong(jwt.getPayload("expire_time"));
        long now = System.currentTimeMillis();
        if (now > expire_time) {
            throw new BizException(ExceptionEnum.TOKEN_EXPIRED);
        }
        // 兼容老的
        if (JWTUtil.verify(token, PRIVATE_KEY.getBytes(StandardCharsets.UTF_8))) {
            return;
        }
        String code = Convert.toStr(jwt.getPayload("code"));
        String userPwd = USER_CACHE.getUserPwd(code);
        if (JWTUtil.verify(token, userPwd.getBytes(StandardCharsets.UTF_8))) {
            return;
        }
        throw new BizException(ExceptionEnum.TOKEN_NOT_EXIST);
    }

    public String getUserToken() {
        return Objects.requireNonNull(getRequest()).getHeader("token");
    }

    public String getTokenUserId() {
        try {
            String token = Objects.requireNonNull(getRequest()).getHeader("token");
            final JWT jwt = JWTUtil.parseToken(token);
            return jwt.getPayload("code").toString();
        } catch (Exception e) {
            return "99999";
        }
    }

    public String getTokenUserId(String token) {
        if (StrUtil.isEmpty(token)) {
            return null;
        }
        try {
            final JWT jwt = JWTUtil.parseToken(token);
            return jwt.getPayload("code").toString();
        } catch (Exception e) {
            return null;
        }
    }

    public HttpServletRequest getRequest() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes();
        return requestAttributes == null ? null : requestAttributes.getRequest();
    }

}
