package com.zzwtec.third.aop.aspect.work;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.zzwtec.third.common.RedisPrefixAndConstant;
import com.zzwtec.third.common.RequestIdContext;
import com.zzwtec.third.common.TokenServiceSupport;
import com.zzwtec.third.common.UrlContents;
import com.zzwtec.third.config.redis.RedisService;
import com.zzwtec.third.model.SysuserCache;
import com.zzwtec.third.utils.BizException;
import com.zzwtec.third.utils.ResultObject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.concurrent.TimeUnit;

/**
 * create by Jomchen on 2018/12/4
 */
@Component("webHandleWork")
public class WebHandleWork extends WorkAbstract {

    private Logger logger = LoggerFactory.getLogger(WebHandleWork.class);

    @Autowired
    private RedisService redisService;
    @Autowired
    private HttpServletRequest request;


    @Override
    public void choiceGenerateRequestId() {
        String requestId = RequestIdContext.getRequestId();
        if (StringUtils.isEmpty(requestId)) {
            requestId = RequestIdContext.generateRequestId();
            RequestIdContext.setRequestId(requestId);
        }
    }

    @Override
    public void removeRequestId() {
        RequestIdContext.removeRequestId();
    }

    @Override
    public void handleError(BizException e) {
        ResultObject errorMessage = (null == e) ? ResultObject.buildError() : ResultObject.buildError(e);
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes instanceof ServletRequestAttributes) {
            ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
            HttpServletResponse response = servletRequestAttributes.getResponse();
            response.setCharacterEncoding("UTF-8");
            response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            PrintWriter writer = null;
            try {
                writer = response.getWriter();
                String errorJson = JSONObject.toJSONString(errorMessage);
                writer.write(errorJson);
            } catch (IOException ioe) {
                logger.error("写入信息到输出流出错：" + ioe.getMessage(), ioe.getCause());
            } finally {
                if (null != writer) {
                    writer.flush();
                    writer.close();
                }
            }
        }
    }

    @Override
    public String checkTimeOut() {
        String uri = request.getRequestURI();
        if (checkPass(uri)) {
            return null;
        }

        String tokenId = TokenServiceSupport.getWebTokenIdFromCookie(request);
        if (StringUtils.isEmpty(tokenId)) {
            return UrlContents.URL_ADM_LOGIN_UI;
        }
        SysuserCache sysuserCache = redisService.getEntity(
                tokenId,
                new TypeReference<SysuserCache>() {}
        );
        if (null == sysuserCache) {
            return UrlContents.URL_ADM_LOGIN_UI;
        }

        redisService.expire(
                tokenId,
                RedisPrefixAndConstant.CACHE_LOGIN_TIME,
                TimeUnit.MINUTES
        );
        return null;
    }

    /**
     * 对指定的地址进行放行
     */
    private boolean checkPass(String uri) {
        if (uri.equals(UrlContents.URL_ROOT)
                || uri.equals(UrlContents.URL_ADM_LOGIN_UI)
                || uri.equals(UrlContents.URL_ADM_LOGIN)
                || uri.startsWith(UrlContents.URL_ADM_LOGFIN_VERIFY_CODE)
                || uri.startsWith("wechat/menu")
                ) {
            // 要经过处理器映射器，但不需要验证登录超时的地址放在这里
            return true;
        } else {
            return false;
        }
    }

}
