package com.fs.app.websocket.auth;

import com.fs.app.utils.JwtUtils;
import com.fs.app.utils.VerifyUtils;
import com.fs.app.websocket.constant.AttrConstant;
import com.fs.common.exception.BaseException;
import com.fs.common.utils.spring.SpringUtils;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;

import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
import java.util.List;
import java.util.Map;

@Slf4j
public class WebSocketConfigurator extends ServerEndpointConfig.Configurator {

    private final JwtUtils jwtUtils = SpringUtils.getBean(JwtUtils.class);

    /**
     * 安全校验
     * @param sec       配置
     * @param request   请求
     * @param response  返回
     */
    @Override
    public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
        Map<String, List<String>> parameterMap = request.getParameterMap();
        if(!parameterMap.containsKey(AttrConstant.LIVE_ID)){
            throw new BaseException("缺少必要的参数");
        }
        if(!parameterMap.containsKey(AttrConstant.USER_ID)){
            throw new BaseException("缺少必要的参数");
        }

        String tokenKey = jwtUtils.getHeader();
        if (!parameterMap.containsKey(tokenKey) && !parameterMap.containsKey(AttrConstant.SIGNATURE)) {
            throw new BaseException("缺少必要的参数");
        }

        Long liveId = Long.valueOf(parameterMap.get(AttrConstant.LIVE_ID).get(0));
        Long userId = Long.valueOf(parameterMap.get(AttrConstant.USER_ID).get(0));

        Map<String, Object> userProperties = sec.getUserProperties();
        userProperties.put(AttrConstant.LIVE_ID, liveId);
        userProperties.put(AttrConstant.USER_ID, userId);
        if (parameterMap.containsKey(AttrConstant.COMPANY_ID)) {
            userProperties.put(AttrConstant.COMPANY_ID, Long.valueOf(parameterMap.get(AttrConstant.COMPANY_ID).get(0)));
        }
        if (parameterMap.containsKey(AttrConstant.COMPANY_USER_ID)) {
            userProperties.put(AttrConstant.COMPANY_USER_ID, Long.valueOf(parameterMap.get(AttrConstant.COMPANY_USER_ID).get(0)));
        }

        // 验证token
        if (parameterMap.containsKey(tokenKey)) {
            String token = parameterMap.get(tokenKey).get(0);
            Claims claims = jwtUtils.getClaimByToken(token);
            if(claims == null || jwtUtils.isTokenExpired(claims.getExpiration())){
                throw new BaseException(jwtUtils.getHeader());
            }

            userProperties.put(AttrConstant.USER_TYPE, 0L);
        }

        // 验证签名
        if (parameterMap.containsKey(AttrConstant.SIGNATURE)) {
            String liveIdStr = parameterMap.get(AttrConstant.LIVE_ID).get(0);
            String userIdStr = parameterMap.get(AttrConstant.USER_ID).get(0);
            String userTypeStr = parameterMap.get(AttrConstant.USER_TYPE).get(0);
            String timestampStr = parameterMap.get(AttrConstant.TIMESTAMP).get(0);
            String signatureStr = parameterMap.get(AttrConstant.SIGNATURE).get(0);

            try {
                if (!VerifyUtils.verifySignature(liveIdStr, userIdStr, userTypeStr, timestampStr, signatureStr)) {
                    throw new BaseException("缺少必要的参数");
                }

                userProperties.put(AttrConstant.USER_TYPE, Long.parseLong(userTypeStr));
            } catch (Exception e) {
                log.warn("webSocket连接验签失败 msg: {}", e.getMessage(), e);
                throw new BaseException("缺少必要的参数");
            }
        }
    }

}
