package com.zanxiang.game.module.sdk.adapter;

import com.zanxiang.game.module.base.pojo.enums.HttpStatusEnum;
import com.zanxiang.game.module.mybatis.entity.GameExt;
import com.zanxiang.game.module.sdk.annotation.PushDataCheck;
import com.zanxiang.game.module.sdk.annotation.UnSignCheck;
import com.zanxiang.game.module.sdk.enums.DeviceTypeEnum;
import com.zanxiang.game.module.sdk.service.IGameExtService;
import com.zanxiang.game.module.sdk.util.SignUtil;
import com.zanxiang.module.util.exception.BaseException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import java.util.Objects;

/**
 * @author : lingfeng
 * @time : 2022-09-28
 * @description : 拦截器
 */
@Component
@Service
@Slf4j
public class WebHandlerAdapter implements HandlerInterceptor {

    @Resource
    private IGameExtService gameExtService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        //数据推送请求加密验证
        PushDataCheck pushDataCheck = handlerMethod.getMethod().getAnnotation(PushDataCheck.class);
        if (pushDataCheck != null) {
            this.pushCheck(request);
        }
        //接口签名验证
        UnSignCheck unSignCheck = handlerMethod.getMethod().getAnnotation(UnSignCheck.class);
        if (unSignCheck == null) {
            return this.signCheck(request);
        }
        return Boolean.TRUE;
    }

    private boolean signCheck(HttpServletRequest request) throws Exception {
        //游戏id和密钥
        String gameId = request.getHeader("gameId");
        String sign = request.getHeader("sign");
        String timestamp = request.getHeader("timestamp");
        String os = request.getHeader("os");
        String deviceType = request.getHeader("deviceType");
        //必传参数判断
        if (StringUtils.isAnyEmpty(gameId, sign, timestamp, os, deviceType)) {
            log.error("非法参数, 请求头中缺少必传参数");
            throw new BaseException(HttpStatusEnum.INVALID_PARAMS.getMsg());
        }
        //前端类型检测
        DeviceTypeEnum deviceTypeEnum = DeviceTypeEnum.getByDeviceType(Integer.valueOf(deviceType));
        if (deviceTypeEnum == null) {
            throw new BaseException(HttpStatusEnum.INVALID_PARAMS.getMsg());
        }
        //签名验证
        GameExt gameExt = gameExtService.getByGameAppId(gameId);
        if (gameExt == null || Strings.isBlank(gameExt.getAppKey())) {
            log.error("非法参数, 游戏id对应的前端密钥appKey不存在, gameId : {}, sign : {}, timestamp : {}, os : {}, deviceType : {}",
                    gameId, sign, timestamp, os, deviceType);
            throw new BaseException(HttpStatusEnum.INVALID_PARAMS.getMsg());
        }
        String str = "appKey=" + gameExt.getAppKey() + "&gameId=" + gameId + "&timestamp=" + timestamp;
        String mySign = SignUtil.MD5(str);
        //签名对比
        if (!Objects.equals(mySign, sign)) {
            log.error("非法参数, 签名错误, mySign : {}, sign : {}, str : {}", mySign, sign, str);
            throw new BaseException(HttpStatusEnum.INVALID_PARAMS.getMsg());
        }
        return Boolean.TRUE;
    }

    private void pushCheck(HttpServletRequest request) throws Exception {
        String sign = request.getParameter("sign");
        String gameId = request.getParameter("gameId");
        String timestamp = request.getParameter("timestamp");
        String nonce = request.getParameter("nonce");
        String server = request.getParameter("server");
        //检查加密必传参数
        if (StringUtils.isAnyBlank(gameId, timestamp, nonce, sign, server)) {
            log.error("参数非法, 缺少必传参数");
            throw new BaseException(HttpStatusEnum.INVALID_PARAMS.getMsg());
        }
        //判断时间戳是否有效
//        if (Long.valueOf(timestamp) + 300L > System.currentTimeMillis() / 1000) {
//            throw new BaseException(HttpStatusEnum.INVALID_PARAMS.getMsg());
//        }
        //签名验证
        GameExt gameExt = gameExtService.getByGameAppId(gameId);
        if (gameExt == null || Strings.isBlank(gameExt.getLoginKey())) {
            throw new BaseException(HttpStatusEnum.INVALID_PARAMS.getMsg());
        }
        //密钥
        String key = null;
        String keyName = null;
        if (Objects.equals(server, "0")) {
            keyName = "appKey=";
            key = gameExt.getAppKey();
        }
        if (Objects.equals(server, "1")) {
            keyName = "loginKey=";
            key = gameExt.getLoginKey();
        }
        if (StringUtils.isAnyBlank(key, keyName)) {
            throw new BaseException(HttpStatusEnum.INVALID_PARAMS.getMsg());
        }
        String str = keyName + key + "&gameId=" + gameId + "&timestamp=" + timestamp + "&nonce=" + nonce + "&server=" + server;
        String mySign = SignUtil.MD5(str);
        //签名对比
        if (!Objects.equals(mySign, sign)) {
            log.error("非法参数, pushCheck签名错误, mySign : {}, sign : {}, str : {}", mySign, sign, str);
            throw new BaseException(HttpStatusEnum.INVALID_PARAMS.getMsg());
        }
    }
}
