package com.ywt.controllers.mg.interceptors;

import com.fasterxml.jackson.databind.JsonNode;

import com.ywt.core.BaseResponse;
import com.ywt.core.MGRight;
import com.ywt.core.utils.Checker;
import com.ywt.core.utils.serializers.JsonSerializer;
import com.ywt.domain.entity.center.MGAdmins;
import com.ywt.domain.entity.center.MGAdminsRepository;
import com.ywt.service.AuthService;
import com.ywt.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
//import redis.clients.jedis.JedisCommands;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

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

    @Autowired
    private AuthService authService;

    @Autowired
    private UserService userService;

    @Autowired
    private MGAdminsRepository mgAdminsRepository;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;


    private void toResponse(BaseResponse response, HttpServletResponse httpServletResponse) throws IOException {
        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);
        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 {
//        System.out.println(httpServletRequest.getRequestURI());
//        System.out.println("++++++++++++++++++++++++++++++++++++++");
//        Map map = httpServletRequest.getParameterMap();
//        System.out.println(JsonSerializer.toJson(map));

        settingWebAppContextParam(httpServletRequest);

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

        HandlerMethod handlerMethod = (HandlerMethod) o;
        // 获取权限注解
        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;
        }

        // 专门处理 眼镜客户端的下载问题(眼镜客户端的下载没法携带 auth-data 参数，故通过 url进行匹配处理)
        if (requestUrl.endsWith("/glasses/drugs/downloadDrugListFile")) {
            // 获取参数
            String params = httpServletRequest.getParameter("randomValue");
            if (Checker.isNone(params) || redisTemplate.opsForValue().get(params)== null) {
                BaseResponse baseResponse = new BaseResponse();
                baseResponse.setCode(BaseResponse.NO_RIGHT);
                baseResponse.setInfo("链接失效");
                toResponse(baseResponse, httpServletResponse);
                return false;
            }
            return true;
        }

        // 需要验证
        if (requestUrl.startsWith("/glasses/mg") &&
                !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;
        }

        /* todo: 暂时再次更改为不采用实时的方式处理，这样会加快接口请求的速度
        // 需要登陆，设置其它的值
        if (!checkLogin()) {
            BaseResponse baseResponse = new BaseResponse();
            baseResponse.setCode(BaseResponse.NO_RIGHT);
            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)) {
            try {
                JsonNode jsonNode = JsonSerializer.readToNode(authData);
                if (jsonNode.get("adminId") != null) {
                    WebAppContext.current().setAdminId(Checker.parseInt(jsonNode.get("adminId").asText("0")));
                }
                if (jsonNode != null && jsonNode.get("shopId") != null) {
                    WebAppContext.current().setShopId(Checker.parseInt(jsonNode.get("shopId").asText("0")));
                }
                if (jsonNode != null && jsonNode.get("hospitalId") != null) {
                    WebAppContext.current().setHospitalId(Checker.parseInt(jsonNode.get("hospitalId").asText("0")));
                }
            } catch (Exception e) {
                logger.error("settingWebAppContextParam:{}", e.getMessage(), e);
            }
        }
    }


    /**
     * 判断是否登陆，通过判断是否登陆来设置其它所需要的参数
     *
     * @return boolean
     */
    private boolean checkLogin() {
        int currentAdminId = userService.getAdminId();
        if (currentAdminId <= 0) {
            return false;
        }
        MGAdmins mgAdmins = mgAdminsRepository.findById(currentAdminId).orElse(null);
        if (Checker.isNone(mgAdmins)) {
            return false;
        }
        if (!Checker.isNone(mgAdmins.getData())) {
            try {
                JsonNode jsonNode = JsonSerializer.readToNode(mgAdmins.getData());
                if (jsonNode.get("shopId") != null) {
                    WebAppContext.current().setShopId(Checker.parseInt(jsonNode.get("shopId").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) throws Exception {

    }

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

    }
}

