package com.ywt.outpatient.interceptors;

import com.ywt.biz.common.constant.YwtCommonRespCode;
import com.ywt.biz.common.enums.TerminalEnum;
import com.ywt.biz.common.exception.YwtCommonException;
import com.ywt.biz.common.util.CacheUtil;
import com.ywt.biz.common.util.serializers.JsonSerializer;
import com.ywt.gapi.ResultCode;
import com.ywt.gapi.doctor.DoctorInfo;
import com.ywt.gapi.doctor.DoctorService;
import com.ywt.gapi.doctor.GetDoctorRequest;
import com.ywt.gapi.doctor.GetDoctorResponse;
import com.ywt.gapi.user.*;
import com.ywt.outpatient.core.BaseResponse;
import com.ywt.outpatient.core.Constant;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

/**
 * Created by huangguoping.
 */
@Service("userLoginInterceptor")
public class UserLoginInterceptor implements HandlerInterceptor {
    private final Logger logger = LoggerFactory.getLogger(UserLoginInterceptor.class);
    @Autowired
    private RedisTemplate redisTemplate;

    @DubboReference
    private UserService userServiceBlockingStub;

    @DubboReference
    private DoctorService doctorServiceBlockingStub;

    @DubboReference
    private MerchantService merchantServiceBlockingStub;

    private ThreadLocal<Boolean> refreshAuth = new ThreadLocal<>();

    private User findByUserId(int userId) {
        try {
            return (User) CacheUtil.getInstance().get(String.format("u_%s", userId), new Callable<Object>() {
                @Override
                public Object call() throws Exception {
                    UserRequest request = UserRequest.newBuilder().setUserid(userId).build();
                    UserResponse userResponse = userServiceBlockingStub.findByUserId(request);
                    if (userResponse.getResult().getCode() == ResultCode.SUCCEED) {
                        return userResponse.getUser();
                    }
                    throw new YwtCommonException(YwtCommonRespCode.P_ERR, String.format("查找不到用户：%s", userResponse.getResult().getInfo()));
                }
            });
        } catch (Exception e) {
            logger.error("UserLoginInterceptor#findByUserId(userId={} ):\n {}", userId, e.getMessage(), e);
        }
        return null;
    }

    private DoctorInfo getDoctor(int doctorId) {
        try {
            return (DoctorInfo) CacheUtil.getInstance().get(String.format("d_%s", doctorId), new Callable<Object>() {
                @Override
                public Object call() throws Exception {
                    GetDoctorRequest request = GetDoctorRequest.newBuilder().setDoctorId(doctorId).build();
                    GetDoctorResponse getDoctorResponse = doctorServiceBlockingStub.getDoctor(request);
                    if (getDoctorResponse.getResult().getCode() == ResultCode.SUCCEED) {
                        return getDoctorResponse.getDoctorInfo();
                    }
                    throw new YwtCommonException(YwtCommonRespCode.P_ERR, String.format("获取医生信息(%d): %s", doctorId, getDoctorResponse.getResult().getInfo()));
                }
            });
        } catch (Exception e) {
            logger.error("UserLoginInterceptor#getDoctor(doctorId={} ):\n {}", doctorId, e.getMessage(), e);
        }
        return null;
    }

    private GetUserInfoResponse getHealthUser(int userId) {
        try {
            return (GetUserInfoResponse) CacheUtil.getInstance().get(String.format("hu_%s", userId), new Callable<Object>() {
                @Override
                public Object call() throws Exception {
                    GetUserInfoRequest request = GetUserInfoRequest.newBuilder().setUserId(userId).build();
                    GetUserInfoResponse getUserInfoResponse = merchantServiceBlockingStub.getUserInfo(request);
                    if (getUserInfoResponse.getResult().getCode() == ResultCode.SUCCEED) {
                        return getUserInfoResponse;
                    }
                    return null;
                }
            });
        } catch (Exception e) {
            logger.error("UserLoginInterceptor#getHealthUser(userId={} ):\n {}", userId, e.getMessage(), e);
        }
        return null;
    }


    private void toResponse(BaseResponse response, HttpServletResponse httpServletResponse) throws IOException {
        httpServletResponse.addHeader("Content-Type", "application/json;charset=UTF-8");
        String responseData = JsonSerializer.toJson(response);
        httpServletResponse.setStatus(200);
        byte[] responseDataBytes = responseData.getBytes("utf-8");
        httpServletResponse.setContentLength(responseDataBytes.length);
        httpServletResponse.getOutputStream().write(responseDataBytes);
    }

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {

        refreshAuth.set(false);
//        HandlerMethod handlerMethod = (HandlerMethod) o;
//        UserLogin userLogin = handlerMethod.getMethod().getAnnotation(UserLogin.class);
//        if (userLogin == null) {
//            userLogin = handlerMethod.getMethod().getDeclaringClass().getAnnotation(UserLogin.class);
//        }
//
//        if (userLogin != null && userLogin.need() == false) {
//            return true;
//        }

//        GetOffcialUserInfoRequest getOffcialUserInfoRequest = GetOffcialUserInfoRequest.newBuilder()
//                .setHospitalId(0)
//                .setUnionId(WebAppContext.current().getUnionId())
//                .build();
//
//        GetOffcialUserInfoResponse getOffcialUserInfoResponse = userServiceBlockingStub.getOffcialUserInfo(getOffcialUserInfoRequest);
//        Result result = getOffcialUserInfoResponse.getResult();
//
//        if (result.getCode() == ResultCode.SUCCEED) {
//            WebAppContext.current().setUserId(getOffcialUserInfoResponse.getUserId());
//        } else {
//            BaseResponse response = new BaseResponse();
//            toResponse(response.failed(BaseResponse.NO_RIGHT, "用户未绑定"), httpServletResponse);
//            return false;
//        }

//        String token = httpServletRequest.getParameter("token");
//        BaseResponse response = new BaseResponse();
//        if (Checker.isNone(token)) {
////            response.setCode(response.PARAMETER_ERROR);
////            response.setInfo("无效的token");
//            response.failed(BaseResponse.PARAMETER_ERROR, "无效的token");
//            toResponse(response, httpServletResponse);
//            return false;
//
//        } else {
//            try {
//                String keys = String.format(RedisCacheKey.TOKEN_LOGIN_INFO_KEY, token);
//                //根据TOKEN去REDIS拿信息，存在：修改超时时间，不存在，返回，重新登陆.
//                if (jedisClient.exists(keys)) {
//                    jedisClient.expireAt(keys, (System.currentTimeMillis() / 1000) + 60 * 180);// 180分钟后过期
//
//                    WebAppContext.current().setTokenID(token);
//                    return true;
//                } else {
//                    response.setCode(response.PARAMETER_ERROR);
//                    response.setInfo("token失效,请重新登陆..");
//                    toResponse(response, httpServletResponse);
//                    return false;
//                }
//            } catch (Exception e) {
//                response.setCode(response.APP_EXCEPTION);
//                response.setInfo(e.toString());
//            }
//        }

        if (WebAppContext.current().getUserId() > 0) {
            User currUser = findByUserId(WebAppContext.current().getUserId());
            if (currUser != null) {
                //System.out.println(JsonSerializer.toJson(currUser));
                if (currUser.getUsertype() == 2) { //医生用户
                    if (WebAppContext.current().getTerminal() == TerminalEnum.DoctorWxOfficial.getValue() ||
                            WebAppContext.current().getTerminal() == TerminalEnum.TAI_HE_INTERNET_HOSPITAL_DOCTOR_WX_OFFICIAL.getValue() ||
                            WebAppContext.current().getTerminal() == TerminalEnum.DOCTOR_MINI_PROGRAM.getValue()) {
                        DoctorInfo doctorInfo = getDoctor(WebAppContext.current().getUserId());
                        //System.out.println(JsonSerializer.toJson(doctorInfo));
                        if (doctorInfo != null && doctorInfo.getStatus() == 1) { //禁用
                            httpServletResponse.addHeader("x-userid", "0");
                            httpServletResponse.addHeader("x-unionid", WebAppContext.current().getUnionId());
                            httpServletResponse.addHeader("x-openid", WebAppContext.current().getOpenId());

                            Map<String, Object> map = new HashMap<>();
                            map.put("unionId", WebAppContext.current().getUnionId());
                            map.put("userId", 0);
                            map.put("openId", WebAppContext.current().getOpenId());
                            httpServletResponse.addHeader("Auth-Data", JsonSerializer.toJson(map));
                            //System.out.println("---------------------- refreshAuth --");
                            WebAppContext.current().setUserId(0);

                            httpServletResponse.setStatus(403);
                            return false;
                        }

                        //医生用户，未被禁用，标记医生在线状态
                        String key = String.format(Constant.DOCTOR_ONLINE_KEY, WebAppContext.current().getUserId());
                        redisTemplate.opsForValue().set(key, "1", (System.currentTimeMillis() / 1000) + 60 * 15, TimeUnit.SECONDS);
                    }
                } else if (currUser.getUsertype() == 4 || currUser.getUsertype() == 8) { //医商和代表
                    GetUserInfoResponse getUserInfoResponse = getHealthUser(WebAppContext.current().getUserId());
                    if (getUserInfoResponse != null && getUserInfoResponse.getStatus() == 1) { //禁用
                        WebAppContext.current().setUserId(0);

                        Map<String, Object> map = new HashMap<>();
                        map.put("unionId", WebAppContext.current().getUnionId());
                        map.put("userId", 0);
                        map.put("openId", WebAppContext.current().getOpenId());
                        httpServletResponse.addHeader("Auth-Data", JsonSerializer.toJson(map));

                        httpServletResponse.setStatus(403);
                        return false;
                    }
                } else if (currUser.getUsertype() == 1) { //普通用户
                }
            }
        }
        return true;
    }

    @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 {
        if (refreshAuth.get()) {
            httpServletResponse.addHeader("x-userid", "0");
            httpServletResponse.addHeader("x-unionid", WebAppContext.current().getUnionId());
            httpServletResponse.addHeader("x-openid", WebAppContext.current().getOpenId());
            System.out.println("---------------------- refreshAuth");
        }
    }
}
