package com.app.framework.core.api.filter;

import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.ContentType;
import com.alibaba.fastjson.JSON;
import com.app.framework.core.api.constant.ApiConstant;
import com.app.framework.core.api.request.ApiHttpServletRequest;
import com.app.framework.core.api.request.ApiLoginUser;
import com.app.framework.core.api.service.ApiService;
import com.app.framework.core.api.utils.ApiExcludeRegisterCenter;
import com.app.framework.core.support.view.form.AjaxResult;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * API接口身份认证拦截器
 * 所有资源都是受保护的，需要排除的资源通过ApiExcludeRegisterCenter注册。
 * 根据请求头中的Authorization信息，验证用户身份，并将用户ID（apiLoginUserId参数）放入request
 */
public class ApiHttpServletRequestFilter implements Filter {
    private Logger logger = LoggerFactory.getLogger(ApiHttpServletRequestFilter.class);

    private String loginUri = "/login";

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        String loginUri = filterConfig.getInitParameter("loginUri");
        if (StringUtils.isNotBlank(loginUri)) {
            this.loginUri = loginUri;
        }
        String excludedUri = filterConfig.getInitParameter("excludedUri");
        if (StringUtils.isNotBlank(excludedUri)) {
            String[] excludedUris = excludedUri.split(",");
            ApiExcludeRegisterCenter.register(excludedUris);
        }
    }

    @Override
    public void doFilter(ServletRequest srequest, ServletResponse sresponse,
                         FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) srequest;
        HttpServletResponse response = (HttpServletResponse) sresponse;
        //跨域嗅探(跨域请求时会在真正的请求之前发送一次options请求,用于嗅探.此时是不携带请求头信息的,且不能做其他处理)
        if (request.getMethod().equals("OPTIONS")) {
            chain.doFilter(srequest, sresponse);
        }
        //正式请求
        else {
            //获取请求的uri
            String uri = request.getRequestURI();
            //获取Authorization（初次登录时没有Authorization）
            String Authorization = request.getHeader(ApiConstant.HEADER_AUTHORIZATION);
            //获取Platform
            String Platform = request.getHeader(ApiConstant.HEADER_PLATFORM);
//			if(logger.isInfoEnabled()) {
//				logger.info(String.format("身份认证[URI = %s][Authorization = %s][Platform = %s]：", uri, Authorization, Platform));
//			}
            //认证
            if (StringUtils.isNotBlank(loginUri) && uri.indexOf(loginUri) > -1) {//登录，不验证Authorization
                chain.doFilter(srequest, sresponse);
            } else if (ApiExcludeRegisterCenter.isExcluded(uri)) {//被排除的uri，无需认证身份，但获取apiLoginUser值
                if (StringUtils.isNotBlank(Authorization)) {
                    AjaxResult<ApiLoginUser> result = this.IDAuth(Authorization, Platform);
                    if (result.success()) {
                        ApiLoginUser apiLoginUser = result.getData();
                        request.setAttribute("apiLoginUser", apiLoginUser);
                        chain.doFilter(new ApiHttpServletRequest(request, apiLoginUser.getId()), sresponse);
                    } else {
                        chain.doFilter(srequest, sresponse);
                    }
                } else {
                    chain.doFilter(srequest, sresponse);
                }
            } else {//其他请求，需验证Authorization
                //身份认证
                AjaxResult<ApiLoginUser> result = this.IDAuth(Authorization, Platform);
                if (result.success()) {
                    ApiLoginUser apiLoginUser = result.getData();
                    request.setAttribute("apiLoginUser", apiLoginUser);
                    chain.doFilter(new ApiHttpServletRequest(request, apiLoginUser.getId()), sresponse);
                } else {
                    ServletUtil.write(response, JSON.toJSONString(result), ContentType.JSON.toString(StandardCharsets.UTF_8));
                }
            }
        }
    }

    @Override
    public void destroy() {

    }

    /**
     * 身份认证
     *
     * @param Authorization
     * @param Platform
     */
    private AjaxResult<ApiLoginUser> IDAuth(String Authorization, String Platform) {
        AjaxResult<ApiLoginUser> result = AjaxResult.wrap(false);
        if (StringUtils.isNotBlank(Authorization)) {
            ApiService apiService = SpringUtil.getBean(ApiService.class);
            result = apiService.checkToken(Platform, Authorization);
            if (!result.success()) {
                result.setCode(ApiConstant.ID_AUTH_FAILURE);
                result.setMsg("身份认证失败");
            }
        } else {
            result.setCode(ApiConstant.ID_AUTH_FAILURE);
            result.setMsg("请在请求头中传入Authorization参数");
        }
        return result;
    }
}
