package com.sckw.core.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sckw.core.model.enums.SystemTypeEnum;
import com.sckw.core.web.config.CustomConfig;
import com.sckw.core.exception.SystemException;
import com.sckw.core.model.constant.Global;
import com.sckw.core.utils.EncryUtil;
import com.sckw.core.utils.StringUtils;
import com.sckw.core.web.constant.HttpStatus;
import com.sckw.core.web.constant.RequestConstant;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.core.web.model.LoginEntInfo;
import com.sckw.core.web.model.LoginUserInfo;
import com.sckw.redis.utils.RedissonUtils;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.*;

/**
 * @desc: 登录过滤
 * @author: czh
 * @date: 2023/6/14
 */
@Component
public class LoginFilter implements Filter {

    private static final List<String> EXCLUDEPATH = new ArrayList<>();

    @Autowired
    CustomConfig customConfig;

    /**
     * @desc: 初始化放行路径
     * @author: czh
     */
    @PostConstruct
    private void initExcludePath() {
        String links = customConfig.getLinks();
        if (StringUtils.isNotBlank(links)) {
            EXCLUDEPATH.addAll(Arrays.asList(links.split(",")));
        }
    }


    /**
     * @desc: 1、不需要token的请求直接放行
     * 2、取token，校验
     * 3、token校验没问题，判断当前用户角色 平台管理员直接放行
     * 4、校验菜单权限，管理员不用校验，普通用户需要
     * 4、菜单权限没问题，校验企业资质是否过期
     * @author: czh
     * @date: 2023/6/29
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws ServletException, IOException, SystemException{

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String requestUri = request.getRequestURI();
        /*1、不用token的接口直接放行*/
        if (EXCLUDEPATH.contains(requestUri)) {
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }

        /*2、校验token有效性*/
        //token解析后为用户id
        String token = request.getHeader(RequestConstant.TOKEN);
        if (StringUtils.isBlank(token)) {
            throw new SystemException(HttpStatus.PARAMETERS_MISSING_CODE, HttpStatus.TOKEN_MISSING);
        }

        String key;
        try {
            key = EncryUtil.descry(Global.PRI_KEY, token);
        } catch (Exception e) {
            throw new SystemException(HttpStatus.PARAMETERS_MISSING_CODE, HttpStatus.TOKEN_ERROR);
        }

        //从redis获取用户信息
        String clientType = request.getHeader(RequestConstant.CLIENT_TYPE);
        String systemType = request.getHeader(RequestConstant.SYSTEM_TYPE);
        String userInfo = RedissonUtils.getString(Global.getFullUserLoginKey(Integer.parseInt(systemType), Long.parseLong(key), clientType));
        if (StringUtils.isBlank(userInfo)) {
            throw new SystemException(HttpStatus.UN_LOGIN_CODE, HttpStatus.UN_LOGIN_MESSAGE);
        }

        //将redis里的用户信息存入内存中，避免业务操作多次从redis获取值*/
        LoginUserInfo loginUserInfo = JSONObject.parseObject(userInfo, LoginUserInfo.class);
        LoginUserHolder.set(loginUserInfo);
        //暂时这样写一下，有的接口需要给LoginUserHolder赋值
        if ("/kwsMenu/findMenuTree".equals(requestUri) || "/kwsDept/findDeptTree".equals(requestUri)) {
            RedissonUtils.putString(Global.getFullUserLoginKey(Integer.parseInt(systemType), Long.parseLong(key), clientType), JSON.toJSONString(loginUserInfo), Global.PC_TOKEN_EXPIRE);
            filterChain.doFilter(servletRequest, servletResponse);
            LoginUserHolder.remove();
            return;
        }

        /*3、平台管理员直接放行*/
        if (loginUserInfo.getIsMain() == Global.YES && Integer.parseInt(systemType) == SystemTypeEnum.MANAGE.getCode()) {
            RedissonUtils.putString(Global.getFullUserLoginKey(Integer.parseInt(systemType), Long.parseLong(key), clientType), JSON.toJSONString(loginUserInfo), Global.PC_TOKEN_EXPIRE);
            filterChain.doFilter(servletRequest, servletResponse);
            LoginUserHolder.remove();
            return;
        }

        //管理员不限制权限，按钮有权限才放行
        if (loginUserInfo.getIsMain() != Global.YES && !checkMenu(systemType + Global.COLON + key, requestUri)) {
            LoginUserHolder.remove();
            throw new SystemException(HttpStatus.AUTHORITY_NO_CODE, HttpStatus.ACCESS_FIAL);
        }

        /*4、企业信息等校验*/
        //特殊处理，认证接口不校验资质
        if (!"/kwsEnt/register".equals(requestUri)) {
            checkEntInfo(loginUserInfo);
        }

        RedissonUtils.putString(Global.getFullUserLoginKey(Integer.parseInt(systemType), Long.parseLong(key), clientType), JSON.toJSONString(loginUserInfo), Global.PC_TOKEN_EXPIRE);
        filterChain.doFilter(servletRequest, servletResponse);
        LoginUserHolder.remove();
    }

    /**
     * @param loginUserInfo 登录信息
     *                      产品（孙平逸夫）要求，只要第一次审批通过了，之后资质过期、重新审批背驳回，也不影响权限，不控制
     * @desc: 企业校验
     * @author: czh
     * @date: 2023/6/29
     */
    private static void checkEntInfo(LoginUserInfo loginUserInfo) {
        /*4、如果企业资质有效期已过，企业普通用户和管理员均不能访问*/
        Long entId = loginUserInfo.getEntId();
        String enterpriseInfo = RedissonUtils.getString(Global.REDIS_ENTERPRISE_PREFIX + entId);
        //正常不存在企业等信息为空还能走到这里的请求，因为只能访问放开的权限，如果有恶意请求，这里会过滤
        if (StringUtils.isBlank(enterpriseInfo)) {
            LoginUserHolder.remove();
            throw new SystemException(HttpStatus.CODE_60603, HttpStatus.ENT_NOT_EXISTS);
        }

        //企业资料审批状态校验
        LoginEntInfo loginEntInfo = JSON.parseObject(enterpriseInfo, LoginEntInfo.class);
        if (!loginEntInfo.getValid()) {
            LoginUserHolder.remove();
            throw new SystemException(HttpStatus.CODE_60603, HttpStatus.ENTCERTIFICATES_INVAILD);
        }
        RedissonUtils.putString(Global.REDIS_ENTERPRISE_PREFIX + entId, enterpriseInfo, Global.PC_TOKEN_EXPIRE);
//        int approval = loginEntInfo.getApproval();
//        if (approval == ApprovalEnum.NO.getCode() || approval == ApprovalEnum.PROCESS.getCode() || approval == ApprovalEnum.PASS.getCode()) {
//            LoginUserHolder.remove();
//            throw new SystemException(HttpStatus.AUTHORITY_NO_CODE, HttpStatus.ACCESS_FIAL);
//        }
//
//        List<EntCertificateInfo> certificateInfoList = loginEntInfo.getCertificateInfo();
//        if (CollectionUtils.isEmpty(certificateInfoList)) {
//            LoginUserHolder.remove();
//            throw new SystemException(HttpStatus.AUTHORITY_NO_CODE, HttpStatus.ACCESS_FIAL);
//        }
//
//        //有效期检验
//        for (EntCertificateInfo entCertificateInfo : certificateInfoList){
//            Date expireTime = entCertificateInfo.getExpireTime();
//            if (DateUtil.compare(new Date(), expireTime) > 0) {
//                LoginUserHolder.remove();
//                throw new SystemException(HttpStatus.AUTHORITY_NO_CODE, HttpStatus.ACCESS_FIAL);
//            }
//        }
    }

    /**
     * @param key 用户菜单权限key  url 当前请求url
     * @return boolean
     * @desc: 校验url权限
     * @author: czh
     * @date: 2023/6/28
     */
    private boolean checkMenu(String key, String url) {
        return RedissonUtils.contains(Global.REDIS_SYS_MENU_PREFIX + key, url);
    }


}
