package com.ruoyi.interceptor;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.ruoyi.annotations.UserLoginToken;
import com.ruoyi.code.PublicCommon;
import com.ruoyi.code.Token;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.enums.RestExceptionEnum;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.frequency.customer.entity.Customer;
import com.ruoyi.frequency.customer.mapper.CustomerMapper;
import com.ruoyi.frequency.sale.entity.Sale;
import com.ruoyi.frequency.sale.mapper.SaleMapper;
import com.ruoyi.frequency.store.entity.Store;
import com.ruoyi.frequency.store.mapper.StoreMapper;
import com.ruoyi.response.ErrorResponseData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;


/**
 * 登陆拦截器
 */
@Component
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {

        if (handler instanceof org.springframework.web.servlet.resource.ResourceHttpRequestHandler) {
            return true;
        }
        // 如果不是映射到方法直接通过
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();

        //检查有没有需要用户权限的注解
        if (method.isAnnotationPresent(UserLoginToken.class)) {
            return checkUserToken(request, response,method);
        }
        return true;
    }

    /**
     * 渲染json对象
     */
    private static void renderJson(HttpServletResponse response, Object jsonObject) {
        try {
            response.setContentType("application/json");
            response.setCharacterEncoding("UTF-8");
            PrintWriter writer = response.getWriter();
            writer.write(JSON.toJSONString(jsonObject));
        } catch (IOException e) {
            throw new ServiceException("");
        }
    }

    private boolean checkUserToken(HttpServletRequest request, HttpServletResponse response,Method method) {
        String token = request.getHeader("token");

        //请求头中没有token字段
        if (StringUtils.isEmpty(token)) {
            renderJson(response, new ErrorResponseData(
                    RestExceptionEnum.TOKEN_EXPIRED.getCode(), RestExceptionEnum.TOKEN_EXPIRED.getMessage()));
            return false;
        }

        //根据token 获取用户id
        String userId = redisTemplate.opsForValue().get(token);

        //用户id为空
        if (StringUtils.isBlank(userId)) {
            renderJson(response, new ErrorResponseData(
                    RestExceptionEnum.TOKEN_EXPIRED.getCode(), RestExceptionEnum.TOKEN_EXPIRED.getMessage()));
            return false;
        }

        //判断当前接口有无权限
        Boolean verifyPermissions = verifyPermissions(method, token);
        if (!verifyPermissions){
            renderJson(response, new ErrorResponseData(
                    RestExceptionEnum.TOKEN_EXPIRED.getCode(), RestExceptionEnum.TOKEN_EXPIRED.getMessage()));
            return false;
        }

        //验证登入用户是否合法
        Boolean verifyLoginUser = verifyLoginUser(token,userId);
        if (!verifyLoginUser){
            renderJson(response, new ErrorResponseData(
                    RestExceptionEnum.TOKEN_EXPIRED.getCode(), RestExceptionEnum.TOKEN_EXPIRED.getMessage()));
            return false;
        }

        //验证当前token 是否有效
//        Object o = redisTemplate.opsForHash().get(Token.TOKEN_MAP, userId + "");
//        if (ObjectUtil.isNotEmpty(o)) {
//            if (!token.equals(o.toString())) {
//                renderJson(response, new ErrorResponseData(
//                        RestExceptionEnum.TOKEN_EXPIRED.getCode(), RestExceptionEnum.TOKEN_EXPIRED.getMessage()));
//                return false;
//            }
//        }

        redisTemplate.opsForValue().set(token, userId, Token.EXPIRE_SECOND, TimeUnit.DAYS);

        return true;
    }


    @Autowired
    private CustomerMapper customerMapper;

    @Autowired
    private StoreMapper storeMapper;

    @Autowired
    private SaleMapper saleMapper;

    /**
     * 验证登入用户是否合法
     */
    private Boolean verifyLoginUser(String token,String userId) {

        if (!token.startsWith(Token.customer) && !token.startsWith(Token.store) && !token.startsWith(Token.sale)&& !token.startsWith(Token.enterprise)){
            return false;
        }

        if (token.startsWith(Token.customer)) {
            //验证用户有没有被禁用删除
            Customer customer = customerMapper.selectById(Long.valueOf(userId));
            return customer != null && customer.getDelFlag().equals(PublicCommon.启用);
        }else if(token.startsWith(Token.store)){
            //验证商家有没有被禁用删除
            Store store = storeMapper.selectById(Long.valueOf(userId));
            return store != null && store.getDelFlag().equals(PublicCommon.启用);
        }else if(token.startsWith(Token.sale)){
            //验证商家有没有被禁用删除
            Sale sale = saleMapper.selectById(Long.valueOf(userId));
            return sale != null && sale.getDelFlag().equals(PublicCommon.启用);
        }else if(token.startsWith(Token.enterprise)){
//            //验证商家有没有被禁用删除
//            Store store = storeMapper.selectById(Long.valueOf(userId));
//            return store != null && store.getDelFlag().equals(PublicCommon.启用);
        }

        return true;
    }

    /**
     * 判断当前接口有无权限
     * @param method
     */
    private Boolean verifyPermissions(Method method,String token) {
        String[] userTokenPres = method.getAnnotation(UserLoginToken.class).userTokenPre();
        if (userTokenPres.length > 0){
            long count = Arrays.stream(userTokenPres).filter(s -> {
                //当前登入用户token前缀
                String tokenPre = "";
                if (token.startsWith(Token.customer)) {
                    tokenPre = Token.customer;
                } else if (token.startsWith(Token.store)){
                    tokenPre = Token.store;
                }else if (token.startsWith(Token.sale)){
                    tokenPre = Token.sale;
                }else if (token.startsWith(Token.enterprise)){
                    tokenPre = Token.enterprise;
                }
                return ObjectUtil.equal(s, tokenPre);
            }).count();
            return count != 0;
        }
        return true;
    }

}

