package com.yunzhi.marketing.interceptor;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yunzhi.marketing.base.ResponseBean;
import com.yunzhi.marketing.center.sysUser.entity.SysToken;
import com.yunzhi.marketing.center.sysUser.service.ISysTokenService;
import com.yunzhi.marketing.center.taUser.entity.TaButtonUriMap;
import com.yunzhi.marketing.center.taUser.entity.TaUserRole;
import com.yunzhi.marketing.center.taUser.service.ITaButtonUriMapService;
import com.yunzhi.marketing.center.taUser.service.ITaUserRoleService;
import com.yunzhi.marketing.common.JWTUtils;
import com.yunzhi.marketing.common.StringUtils;
import com.yunzhi.marketing.entity.SysButtonInMenu;
import com.yunzhi.marketing.entity.TaRoleButton;
import com.yunzhi.marketing.service.ISysButtonInMenuService;
import com.yunzhi.marketing.service.ITaRoleButtonService;
import com.yunzhi.marketing.third.service.ITaThirdPartyMiniappConfigService;
import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class AccessInterceptor implements HandlerInterceptor {
    
    @Autowired
    private ISysTokenService sysTokenService;
    
    @Autowired
    private ITaUserRoleService taUserRoleService;
    
    @Autowired
    private ITaRoleButtonService taRoleButtonService;
    
    @Autowired
    private ISysButtonInMenuService sysButtonInMenuService;
    
    @Autowired
    private ITaButtonUriMapService taButtonUriMapService;
    
    @Autowired
    private ITaThirdPartyMiniappConfigService taThirdPartyMiniappConfigService;
    
    private String[] whiteList = {
            "/wx/chat", // 聊天暂时不鉴权
            "/api/wx/login",
            "/api/wx/tdCity",
            "/api/wx/preload",
            "/api/admin/signin",
            "/api/taCheckin/activity",
            "/api/wx/qrcode/scene",
		    "/api/center/signin",
            "/api/channel/signin",
		    "/api/admin/taUser/signin",
            "/swagger-resources/configuration/ui",
            "/swagger-resources",
            "/v2/api-docs",
            "/swagger-resources/configuration",
            "/swagger-ui.html",
            "/webjars",
            "/webjars/springfox-swagger-ui",
            "/webjars/springfox-swagger-ui/css/typography.css",
            "/clean/menurole",
            "/clean/buttonrole",
            "/api/admin/taPersonFromRecord",
            "/api/notify",//微信支付所有回调放过
            "/api/refund/",//微信退款所有回调放过
            "/api/fadd/",//所有的法大大回调放过
            "/api/third",
            "/api/third/redirect/",
            "/file/",
            "/api/official/" // 官网接口
    };

    /*
     * 视图渲染之后的操作
     */
    @Override
    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
            throws Exception {

    }

    /*
     * 处理请求完成后视图渲染之前的处理操作
     */
    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
            throws Exception {

    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) throws Exception {
        log.info("接口请求路径是{}",request.getRequestURI());
        //第三方权限校验
        String tokenHeader = request.getHeader("x-token");
        if (!StringUtils.isEmpty(tokenHeader)){
            String appidHeader = request.getHeader("x-appid");
            String nowHeader = request.getHeader("x-time");
            String thirdState = taThirdPartyMiniappConfigService.checkToken(tokenHeader,appidHeader,nowHeader);
            if (thirdState.equals("success")){
                return true;
            }
    
            ResponseBean resp = ResponseBean.error(thirdState , ResponseBean.ERROR_AUTH_FAIL);
            response.addHeader("Content-type", "application/json");
            response.getOutputStream().write(JSONObject.toJSONBytes(resp));
            return false;
        }

        // 白名单跳过
        if (inWhiteList(request)) {
            return true;
        }

        // 微信头必须对
        if (!checkMiniApp(request)) {
            ResponseBean resp = ResponseBean.error("请使用微信请求接口", ResponseBean.ERROR_ILLEGAL_PARAMS);

            response.addHeader("Content-type", "application/json");
            response.getOutputStream().write(JSONObject.toJSONBytes(resp));
            return false;
        }

        // 消息头必须包含 authorization 字段
        String jwtHeader = request.getHeader("authorization");
        if (null == jwtHeader || "".equals(jwtHeader)) {
            ResponseBean resp = ResponseBean.error("请先进行系统登录操作", ResponseBean.ERROR_AUTH_FAIL);

            response.addHeader("Content-type", "application/json");
            response.getOutputStream().write(JSONObject.toJSONBytes(resp));
            return false;
        }

        String[] jwtAuths = jwtHeader.split("Bearer ");
        if (null == jwtAuths || jwtAuths.length < 2 || StringUtils.isEmpty(jwtAuths[1])) {
            ResponseBean resp = ResponseBean.error("权限验证非法, 数据格式不正确", ResponseBean.ERROR_AUTH_FAIL);

            response.addHeader("Content-type", "application/json");
            response.getOutputStream().write(JSONObject.toJSONBytes(resp));
            return false;
        }

        try {
            // 只尝试去解析
            Jwts.parser().setSigningKey(JWTUtils.key).parseClaimsJws(jwtAuths[1]);
        } catch (ExpiredJwtException e) {
            ResponseBean resp = ResponseBean.error("权限验证非法, 身份信息已过期", ResponseBean.ERROR_AUTH_EXPIRED);
            response.addHeader("Content-type", "application/json");
            response.getOutputStream().write(JSONObject.toJSONBytes(resp));
            return false;

        } catch (JwtException e) {
            ResponseBean resp = ResponseBean.error("权限验证非法, " + e.getMessage(), ResponseBean.ERROR_AUTH_FAIL);


            response.addHeader("Content-type", "application/json");
            response.getOutputStream().write(JSONObject.toJSONBytes(resp));
            return false;
        }

        //添加如果执行了登出操作提示先进行登录
        SysToken sysToken = sysTokenService.getById(jwtAuths[1]);
        if (null == sysToken){
            ResponseBean resp = ResponseBean.error("请先进行系统登录操作", ResponseBean.ERROR_AUTH_FAIL);

            response.addHeader("Content-type", "application/json");
            response.getOutputStream().write(JSONObject.toJSONBytes(resp));
            return false;
        }

//        按钮权限校验
//        boolean state = checkButtonRole(request);
//        if (!state){
//            ResponseBean resp = ResponseBean.error("权限验证非法" , ResponseBean.ERROR_AUTH_FAIL);
//
//            response.addHeader("Content-type", "application/json");
//            response.getOutputStream().write(JSONObject.toJSONBytes(resp));
//            return false;
//        }
        
        return true;
    }
    
    //检验按钮权限
    private boolean checkButtonRole(HttpServletRequest request) {
        String action = request.getHeader("x-action");
        if(StringUtils.isEmpty(action)){
            return false;
        }
        //根据路径匹配code 一致继续 否则无权限
        String requestURI = request.getRequestURI();
        String method = request.getMethod();
        TaButtonUriMap taButtonUriMap = taButtonUriMapService.getByURI(requestURI+":"+method);
        if (null == taButtonUriMap){
            return true;
        }
    
        
        if (!taButtonUriMap.getButtonCode().equals(action)){
            return false;
        }
        
        //根据code查询按钮权限
        Map map = JWTUtils.getUserIdAndOrgId(request);
        QueryWrapper<SysButtonInMenu> sysButtonInMenuQueryWrapper = new QueryWrapper<>();
        sysButtonInMenuQueryWrapper.eq("code",action);
        SysButtonInMenu sysButtonInMenu = sysButtonInMenuService.getOne(sysButtonInMenuQueryWrapper);
        if (null == sysButtonInMenu){
            return false;
        }
        //查询角色
        QueryWrapper<TaRoleButton> taRoleButtonQueryWrapper = new QueryWrapper<>();
        taRoleButtonQueryWrapper.eq("btn_id",sysButtonInMenu.getBtnId());
        List<TaRoleButton> taRoleButtonList = taRoleButtonService.list(taRoleButtonQueryWrapper);
        if (taRoleButtonList.size() < 1){
            return true;
        }
        //查询用户
        QueryWrapper<TaUserRole> taUserRoleQueryWrapper = new QueryWrapper<>();
        taUserRoleQueryWrapper.eq("user_id",map.get("userId"));
        TaUserRole taUserRole = taUserRoleService.getOne(taUserRoleQueryWrapper);
        for (TaRoleButton taRoleButton : taRoleButtonList){
            if (taRoleButton.getRoleId().equals(taUserRole.getRoleId())){
                return true;
            }
        }
        
        return false;
    }
    
    private boolean checkMiniApp(HttpServletRequest request) {
        String requestURI = request.getRequestURI();

        // 非微信请求
        if (!requestURI.startsWith("/api/wx")) {
            return true;
        }

        String ua = request.getHeader("user-agent");
        return ua.contains("micromessenger") || ua.contains("MicroMessenger");
    }

    private boolean inWhiteList(HttpServletRequest request) {
        String requestURI = request.getRequestURI();

        for (String it : whiteList) {
            if (requestURI.startsWith(it)) {
                return true;
            }
        }

        return false;
    }
}
