package com.qmth.jkserver.core.inteceptor;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.qmth.jkserver.common.MD5;
import com.qmth.jkserver.constant.SpringContextHolder;
import com.qmth.jkserver.constant.SystemConstant;
import com.qmth.jkserver.core.ApiResult;
import com.qmth.jkserver.core.Token;
import com.qmth.jkserver.core.annotation.TokenValidate;
import com.qmth.jkserver.core.exception.ApiException;
import com.qmth.jkserver.core.exception.JkServerException;
import com.qmth.jkserver.enums.TokenPolicy;
import com.qmth.jkserver.model.BasicSchool;
import com.qmth.jkserver.service.AuthInfoService;
import com.qmth.jkserver.service.CommonCacheService;
import com.qmth.jkserver.util.ServletUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;
import java.util.Optional;

/**
 * 接口鉴权
 *
 * @author tianjun
 */
public class ApiInterceptor extends HandlerInterceptorAdapter {

    private Logger logger = LoggerFactory.getLogger(ApiInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        logger.info("@@API Request URI:" + request.getRequestURI());
        AuthInfoService authInfoService = SpringContextHolder.getBean(AuthInfoService.class);
        CommonCacheService commonCacheService = SpringContextHolder.getBean(CommonCacheService.class);
        Long schoolId = (Long) ServletUtil.getRequestHeaderSchoolId();
        if (Objects.nonNull(schoolId) && schoolId.longValue() > 0) {
            BasicSchool basicSchool = commonCacheService.schoolCache(schoolId);
            Optional.ofNullable(basicSchool).orElseThrow(() -> new JkServerException("学校数据为空"));
            authInfoService.appHasExpired(basicSchool.getCode());
        }
        HandlerMethod method = (HandlerMethod) handler;
        TokenValidate annotation = method.getMethodAnnotation(TokenValidate.class);
        if (annotation != null) {
            if (annotation.policy() != null && TokenPolicy.IGNORE.equals(annotation.policy())) {
                return true;
            }
        }
        String header = StringUtils.trimToNull(request.getHeader("Authorization"));
        if (StringUtils.isNotEmpty(header)) {
            //1 校验token合法性
            String authorization = StringUtils.trimToNull(request.getHeader("Authorization"));
            if (StringUtils.isEmpty(authorization) || !authorization.startsWith("jk")) {
                errorReturn(response, ApiException.TOKEN_INVALID);
                return false;
            }
            String tokenParam = authorization.substring(2);
            Token token = Token.deserialize(tokenParam);
            //2校验签名F
            String timestamp = StringUtils.trimToNull(request.getHeader("timestamp"));
            String sign = StringUtils.trimToNull(request.getHeader("sign"));
            if (StringUtils.isEmpty(timestamp)) {
                errorReturn(response, ApiException.TIMESTAMP_IS_NULL);
                return false;
            }
            if (StringUtils.isEmpty(sign)) {
                errorReturn(response, ApiException.SIGN_INVALID);
                return false;
            }
            StringBuffer stringBuffer = new StringBuffer();
            stringBuffer.append(authorization);
            stringBuffer.append("examCode=").append(token.getExamCode()).append("&");
            stringBuffer.append("timestamp=").append(timestamp).append("&");
            stringBuffer.append("uri=").append(request.getRequestURI()).append("&");
            stringBuffer.append("mac=").append(token.getMac());
            stringBuffer.append(authorization);
            String mysign = MD5.encrypt(stringBuffer.toString());
            if (!mysign.equals(sign)) {
                errorReturn(response, ApiException.SIGN_INVALID);
                return false;
            } else {
                return true;
            }
        } else {
            errorReturn(response, ApiException.TOKEN_NEEDED);
            return false;
        }
    }


    private void errorReturn(HttpServletResponse response, ApiException exception) {
        ApiResult result = new ApiResult();
        result.returnError(exception.getCode(), exception.getMessage());
        try {
            ObjectMapper mapper = new ObjectMapper();
            String returnResult = mapper.writeValueAsString(result);
            logger.debug("响应信息:" + returnResult);
            response.setStatus(200);
            response.setCharacterEncoding(SystemConstant.CHARSET_NAME);
            response.setContentType(SystemConstant.CONTENT_TYPE_JSON + ";charset=" + SystemConstant.CHARSET_NAME);
            response.getWriter().write(returnResult);
        } catch (Exception e) {
        }
    }

    // 获取客户端的IP
    public String getRemoteAddress(HttpServletRequest request) {
        String ip = request.getHeader("X-Real-IP");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip.equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip;
    }
}
