package com.ywt.mg.web.interceptors;

import com.fasterxml.jackson.databind.JsonNode;
import com.ywt.mg.core.MGRight;
import com.ywt.mg.core.utils.Checker;
import com.ywt.mg.core.utils.serializers.JsonSerializer;
import com.ywt.mg.domain.entities.MGAdmins;
import com.ywt.mg.domain.entities.MGAdminsRepository;
import com.ywt.mg.services.AuthService;
import com.ywt.mg.web.BaseResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Created by huangguoping.
 */
@Service
public class AuthInterceptor implements HandlerInterceptor {
    private static Logger logger = LoggerFactory.getLogger(AuthInterceptor.class);

    @Autowired
    private AuthService authService;

    @Autowired
    private MGAdminsRepository mgAdminsRepository;

    private void toResponse(BaseResponse response, HttpServletResponse httpServletResponse) throws Exception {
        httpServletResponse.addHeader("Content-Type", "application/json;charset=UTF-8");
        httpServletResponse.setDateHeader("Expires", 0);
        // 禁止缓存的指令：https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control#%E7%A6%81%E6%AD%A2%E7%BC%93%E5%AD%98
        httpServletResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
        httpServletResponse.setHeader("Pragma", "no-cache");
        String responseData = JsonSerializer.toJson(response);
        if (responseData != null) {
            byte[] responseDataBytes = responseData.getBytes("UTF-8");
            httpServletResponse.setContentLength(responseDataBytes.length);
            httpServletResponse.getOutputStream().write(responseDataBytes);
        }
    }

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {

        settingWebAppContextParam(httpServletRequest);

        // 对 swagger-ui 相关接口进行过滤
        // 本地查看swagger-ui的接口：http://localhost:8067/api/swagger-ui.html 或者 http://localhost:8067/swagger-ui.html
        String requestUrl = httpServletRequest.getRequestURI();
        if (requestUrl.startsWith("/api/swagger-resources")
                || requestUrl.startsWith("/api/v2/api-docs")
                || requestUrl.startsWith("/api/configuration/security")
                || requestUrl.startsWith("/api/configuration/ui")) {
            return true;
        }

        HandlerMethod handlerMethod = (HandlerMethod) o;
        // 如果有错误，可以通过打印下面两行，看进入什么类调用什么方法，默认状态下，post 找不到地址提示 405
//         System.out.println(handlerMethod.getMethod().getName());
//         System.out.println(handlerMethod.getMethod().getDeclaringClass().getSimpleName());

        // 获取权限注解
        MGRight mgRight = handlerMethod.getMethod().getAnnotation(MGRight.class);
        if (mgRight == null) {
            mgRight = handlerMethod.getMethod().getDeclaringClass().getAnnotation(MGRight.class);
        }
        if (mgRight == null) {
            BaseResponse baseResponse = new BaseResponse();
            baseResponse.setCode(BaseResponse.NO_RIGHT);
            if (httpServletResponse.getStatus() == 404) {
                baseResponse.setInfo("路径有误");
            } else {
                baseResponse.setInfo("没有权限");
            }
            toResponse(baseResponse, httpServletResponse);
            return false;
        }

        // 不需要验证
        if (!mgRight.need()) {
            return true;
        }

        /* todo: 暂时再次更改为不采用实时的方式处理，这样会加快接口请求的速度
        // 需要登陆，设置其它的值
        if (!checkLogin()) {
            BaseResponse baseResponse = new BaseResponse();
            baseResponse.setCode(BaseResponse.NO_RIGHT);
            baseResponse.setInfo("请先登录");
            toResponse(baseResponse, httpServletResponse);
            return false;
        }
        */

        // 如果是医院，需要先指定医院
        if (requestUrl.startsWith("/api/hosp/")) {
            int hospitalId = authService.getCurrentHospitalId();
            if (hospitalId == 0) {
                BaseResponse baseResponse = new BaseResponse();
                baseResponse.setCode(BaseResponse.NO_RIGHT);
                baseResponse.setInfo("请先指定医院");
                toResponse(baseResponse, httpServletResponse);
                return false;
            }
        }

        // 判断菜单权限，权限点权限
        if (!authService.hasRight(mgRight.menuCode(), mgRight.rightCode(), mgRight.type())) {
            //没有权限
            BaseResponse baseResponse = new BaseResponse();
            baseResponse.setCode(BaseResponse.NO_RIGHT);
            // 如果访问的是流接口，返回701和前端约定好，如果此时返回401，会跳往登录页面，刚好不想让它跳往登录页
            httpServletResponse.setStatus(701);
            baseResponse.setInfo("没有权限");
            toResponse(baseResponse, httpServletResponse);
            return false;
        }
        return true;
    }

    /**
     * 保存参数
     * @param httpServletRequest {@link HttpServletRequest}
     */
    private void settingWebAppContextParam(HttpServletRequest httpServletRequest){
        String authData = httpServletRequest.getHeader("auth-data");
        if (Checker.isNone(authData)){
            authData = httpServletRequest.getHeader("authdata");
        }
        if (!Checker.isNone(authData)) {
            JsonNode jsonNode = JsonSerializer.readToNode(authData);
            if (!Checker.isNone(jsonNode)) {
                if (jsonNode.get("adminid") != null) {
                    WebAppContext.current().setAdminId(Checker.parseInt(jsonNode.get("adminid").asText("0")));
                }
                if (!Checker.isNone(jsonNode.get("hospitalId"))) {
                    WebAppContext.current().setHospitalId(Checker.parseInt(jsonNode.get("hospitalId").asText("0")));
                }
                if (!Checker.isNone(jsonNode.get("shopId"))) {
                    WebAppContext.current().setShopId(Checker.parseInt(jsonNode.get("shopId").asText("0")));
                }
                if (!Checker.isNone(jsonNode.get("enterpriseId"))) {
                    WebAppContext.current().setEnterpriseId(Checker.parseInt(jsonNode.get("enterpriseId").asText("0")));
                }
                if (!Checker.isNone(jsonNode.get("pharmacyId"))) {
                    WebAppContext.current().setPharmacyId(Checker.parseInt(jsonNode.get("pharmacyId").asText("0")));
                }
            }
        }
    }

    /**
     * 判断是否登陆，通过判断是否登陆来设置其它所需要的参数
     *
     * @return boolean
     */
    private boolean checkLogin() {
        int currentAdminId = authService.getCurrentAdminId();
        if (currentAdminId <= 0){
            return false;
        }
        MGAdmins mgAdmins = mgAdminsRepository.findOne(currentAdminId);
        if (Checker.isNone(mgAdmins) || mgAdmins.getState() != 1) {
            return false;
        }
        if (!Checker.isNone(mgAdmins.getData())) {
            try {
                JsonNode jsonNode = JsonSerializer.readToNode(mgAdmins.getData());
                if (Checker.isNone(jsonNode)){
                    return true;
                }
                if (!Checker.isNone(jsonNode.get("hospitalId"))) {
                    WebAppContext.current().setHospitalId(Checker.parseInt(jsonNode.get("hospitalId").asText("0")));
                }
                if (!Checker.isNone(jsonNode.get("shopId"))) {
                    WebAppContext.current().setShopId(Checker.parseInt(jsonNode.get("shopId").asText("0")));
                }
                if (!Checker.isNone(jsonNode.get("enterpriseId"))) {
                    WebAppContext.current().setEnterpriseId(Checker.parseInt(jsonNode.get("enterpriseId").asText("0")));
                }
                if (!Checker.isNone(jsonNode.get("pharmacyId"))) {
                    WebAppContext.current().setPharmacyId(Checker.parseInt(jsonNode.get("pharmacyId").asText("0")));
                }
            }catch (Exception e){
                logger.error("checkLogin:{}",e.getMessage(), e);
            }
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) {
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e){

    }

}
