package com.crm.login.rely.backend.interceptor;

import com.crm.rely.backend.aspect.ControllerAop;
import com.crm.rely.backend.core.constant.Constants;
import com.crm.rely.backend.core.constant.PrefixEnum;
import com.crm.rely.backend.core.dto.base.BaseResultDto;
import com.crm.rely.backend.core.entity.login.InfoEntity;
import com.crm.rely.backend.exception.ServiceException;
import com.crm.rely.backend.service.RedisService;
import com.crm.rely.backend.util.AESUtil;
import com.crm.rely.backend.util.InteceptorResultUtil;
import com.google.common.base.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

public class LoginInterceptor implements HandlerInterceptor {
    @Autowired
    private RedisService redisService;

    @Autowired
    private ControllerAop controllerAop;

    @Value("${login.single-sign-on:false}")
    private boolean singleSignOn;

    public LoginInterceptor() {

    }

    public LoginInterceptor(RedisService redisService) {
        this.redisService = redisService;
        singleSignOn = false;
    }

    public LoginInterceptor(RedisService redisService, boolean singleSignOn, ControllerAop controllerAop) {
        this.redisService = redisService;
        this.singleSignOn = singleSignOn;
        this.controllerAop = controllerAop;
    }

    //        @Override
//    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object
//    o) throws Exception {
//
//        //如果为OPTIONS直接返回成功
//        if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
//            return true;
//        }
//        boolean isLogin = true;
//        InfoEntity loginInfo = null;
//        String accessToken = httpServletRequest.getHeader(Constants.ACCESS_TOKEN);
//        String token = null;
//        if (Strings.isNullOrEmpty(accessToken)) {
//            isLogin = false;
//        } else {
//            String decryptString = AESUtil.decrypt(accessToken);
//            if (Strings.isNullOrEmpty(decryptString)) {
//                isLogin = false;
//            } else {
//                String[] sp = decryptString.split(Constants.LOGIN_LINK);
//                if (sp == null || sp.length < 2) {
//                    isLogin = false;
//                } else {
//                    token = sp[0];
//                    String source = sp[1];
//                    String value = redisService.getObject(token);
//                    if (Strings.isNullOrEmpty(value)) {
//                        isLogin = false;
//                    } else {
//                        String tokenValidation = redisService.getString(value + Constants.LOGIN_LINK + source);
//                        boolean isSingleSignOn = Strings.isNullOrEmpty(tokenValidation) || (singleSignOn &&
//                        !tokenValidation.equals(token));
//                        if (isSingleSignOn) {
//                            isLogin = false;
//                            redisService.remove(token);
//                        } else {
//                            loginInfo = redisService.getEntity(value,InfoEntity.class);
////                            long time = 0;
////                            if (SourceEnum.WEB.getCode().equals(source)) {
////                                time = Constants.ACCESS_TOKEN_TIME;
////                            } else {
////                                time = Constants.ACCESS_PHONE_TOKEN_TIME;
////                            }
////                            redisService.saveObject(token,value, time);
////                            redisService.saveObject(value + Constants.LOGIN_LINK + source, token, time);
//                        }
//                    }
//                }
//            }
//        }
//
//        if (loginInfo == null || !isLogin) {
//            InteceptorResultUtil.returnResult(httpServletResponse, BaseResultDto.unLogin());
//        } else {
//            if ((PrefixEnum.PREFIX_CUSTOM.equals(loginInfo.getPrefix()) && !loginInfo.getValid().equals(1))) {
//                InteceptorResultUtil.returnResult(httpServletResponse, BaseResultDto.restrictedLogin());
//                if (!Strings.isNullOrEmpty(token)) {
//                    redisService.remove(token);
//                }
//                isLogin = false;
//            }
//        }
//
//        return isLogin;
//    }
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 如果为 OPTIONS 请求，直接返回成功
        if (RequestMethod.OPTIONS.name().equals(request.getMethod())) {
            return true;
        }

        String accessToken = request.getHeader(Constants.ACCESS_TOKEN);
        if (Strings.isNullOrEmpty(accessToken)) {
            return unauthenticatedResponse(response);
        }

        String decryptedToken = AESUtil.decrypt(accessToken);
        if (Strings.isNullOrEmpty(decryptedToken)) {
            return unauthenticatedResponse(response);
        }

        String[] tokenParts = decryptedToken.split(Constants.LOGIN_LINK);
        if (tokenParts == null || tokenParts.length < 2) {
            return unauthenticatedResponse(response);
        }

        String token = tokenParts[0];
        String source = tokenParts[1];
        String userKey = redisService.getObject(token);

        if (Strings.isNullOrEmpty(userKey)) {
            return unauthenticatedResponse(response);
        }

        String validationToken = redisService.getString(userKey + Constants.LOGIN_LINK + source);
        if (isInvalidToken(validationToken, token)) {
            redisService.remove(token);
            return unauthenticatedResponse(response);
        }

        InfoEntity loginInfo = redisService.getEntity(userKey, InfoEntity.class);
        if (loginInfo == null || isRestrictedLogin(loginInfo, token)) {
            return unauthenticatedResponse(response);
        }

        // 登录验证成功
        return true;
    }

    /**
     * 检查 Token 是否无效（包括单点登录情况）
     */
    private boolean isInvalidToken(String validationToken, String currentToken) {
        return Strings.isNullOrEmpty(validationToken) ||
                (singleSignOn && !validationToken.equals(currentToken));
    }

    /**
     * 检查登录是否受限
     */
    private boolean isRestrictedLogin(InfoEntity loginInfo, String token) throws ServiceException {
        if (PrefixEnum.PREFIX_CUSTOM.equals(loginInfo.getPrefix()) && !loginInfo.getValid().equals(1)) {
            redisService.remove(token);
            return true;
        }
        return false;
    }

    /**
     * 返回未登录的响应
     */
    private boolean unauthenticatedResponse(HttpServletResponse response) throws Exception {
        InteceptorResultUtil.returnResult(response, BaseResultDto.unLogin());
        return false;
    }

    @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 {

    }
}
