package cn.pluss.platform.interceptor;

import cn.pluss.platform.annotation.PassToken;
import cn.pluss.platform.api.Result;
import cn.pluss.platform.api.ResultCode;
import cn.pluss.platform.entity.UserInfo;
import cn.pluss.platform.exception.UnauthorizedException;
import cn.pluss.platform.ipLocation.IpLocationService;
import cn.pluss.platform.userInfo.UserInfoService;
import cn.pluss.platform.util.ComUtil;
import cn.pluss.platform.util.IpUtils;
import cn.pluss.platform.util.JwtUtils;
import com.aliyuncs.geoip.model.v20200101.DescribeIpv4LocationResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * @author Djh
 */
public class AuthenticationInterceptor implements HandlerInterceptor {

    @Autowired
    private UserInfoService uiService;

    @Autowired
    private IpLocationService ipLocationService;

    @Value("${ip.config.enabled}")
    private Boolean ipEnable;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (ipEnable.equals(Boolean.TRUE)) {
            String ipAddr = IpUtils.getIpAddr(request);
            DescribeIpv4LocationResponse location = ipLocationService.getLocation(ipAddr);
            if (!"中国".equals(location.getCountry())) {
                throw new UnauthorizedException("非法请求");
            }

            if ("香港".equals(location.getProvince())) {
                throw new UnauthorizedException("非法请求");
            }
        }

        // 如果不是映射到方法直接通过, 跳过静态文件
        if (!(handler instanceof HandlerMethod)) {
            return HandlerInterceptor.super.preHandle(request, response, handler);
        }

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        // 页面请求不做拦截, url无法带header
        boolean annotationPresent = method.isAnnotationPresent(PassToken.class);
        boolean b = !method.isAnnotationPresent(ResponseBody.class);
        if ( annotationPresent || b ) {
            return HandlerInterceptor.super.preHandle(request, response, handler);
        }

        // String uri = request.getRequestURI();
        String token = request.getHeader("token");
        String userId = request.getHeader("userId");

        // 执行认证
        if (token == null) {
            Result<Object> result = new Result<>();
            result.setCode(ResultCode.UNAUTHORIZED);
            ComUtil.responseResult(response, result);
            return false;
        }

        UserInfo ui = uiService.getById(userId);
        if (ui == null) {
            Result<Object> result = new Result<>();
            result.setCode(ResultCode.UNAUTHORIZED);
            ComUtil.responseResult(response, result);
            return false;
        }

        if (!Objects.equals("244", userId)) {
            Result<Object> result = new Result<>();
            result.setCode(ResultCode.UNAUTHORIZED);
            ComUtil.responseResult(response, result);
            return false;
        }

        Object uid = JwtUtils.get("uid", token);
        if (!Objects.equals(userId, uid.toString())) {
            Result<Object> result = new Result<>();
            result.setCode(ResultCode.UNAUTHORIZED);
            ComUtil.responseResult(response, result);
            return false;
        }

        Object expireTime = JwtUtils.get("expire_time", token);
        if (!(expireTime instanceof Long)) {
            Result<Object> result = new Result<>();
            result.setCode(ResultCode.UNAUTHORIZED);
            ComUtil.responseResult(response, result);
            return false;
        }

        if (((Long) expireTime) < System.currentTimeMillis()) {
            Result<Object> result = new Result<>();
            result.setCode(ResultCode.UNAUTHORIZED);
            ComUtil.responseResult(response, result);
            return false;
        }

        try {
            boolean verify = JwtUtils.verify(token, userId);
            if (!verify) {
                Result<Object> result = new Result<>();
                result.setCode(ResultCode.UNAUTHORIZED);
                ComUtil.responseResult(response, result);
                return false;
            }

        } catch (Exception e) {
            Result<Object> result = new Result<>();
            result.setCode(ResultCode.UNAUTHORIZED);
            ComUtil.responseResult(response, result);
            return false;
        }

        return HandlerInterceptor.super.preHandle(request, response, handler);
    }
}
