package com.qs.mp.web.controller.api.callback;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.qs.mp.common.utils.LogUtil;
import com.qs.mp.common.utils.StringUtils;
import com.qs.mp.common.utils.http.HttpHelper;
import com.qs.mp.framework.domain.WxCallbackMsgBody;
import com.qs.mp.framework.security.handle.HostHolder;
import com.qs.mp.framework.service.IWxAccountService;
import com.qs.mp.handler.BodyReaderHttpServletRequestWrapper;
import com.qs.mp.web.controller.common.BaseApiController;
import java.io.IOException;
import java.util.Arrays;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * e签宝回调
 *
 * @author zhongcp
 */
@RestController
@RequestMapping("/service/notify/*")
public class WxCallBackController extends BaseApiController {

  private final Logger logger = LoggerFactory.getLogger(WxCallBackController.class);

  private final String TOKEN = "qXuGAggYMWk5HLXA";

  @Autowired
  private HostHolder hostHolder;

  @Autowired
  private IWxAccountService wxAccountService;

  /**
   * 微信公众号接口配置验证 特别注意，此处不能直接返回echostr，因为最后输出后会加上双引号，导致微信公众号设置页面提示token验证失败。 所以直接通过response写回去
   *
   * @return
   */
  @RequestMapping(value = "/wxcallback", method = RequestMethod.GET)
  public void checkSignature(@RequestParam("signature") String signature,
      @RequestParam("timestamp") String timestamp,
      @RequestParam("nonce") String nonce, @RequestParam("echostr") String echostr,
      HttpServletResponse response) {
    LogUtil.info(logger, "signature:{0}, timestamp:{1}, nonce:{2}, echostr:{3}",
        signature, timestamp, nonce, echostr);
    // 第一步：自然排序
    String[] tmp = {TOKEN, timestamp, nonce};
    Arrays.sort(tmp);
    // 第二步：sha1 加密
    String sourceStr = StringUtils.join(tmp);
    String localSignature = DigestUtils.sha1Hex(sourceStr);
    LogUtil.info(logger, "localSignature:{0}", localSignature);
    // 第三步：验证签名
    if (signature.equals(localSignature)) {
      LogUtil.info(logger, "签名验证通过，返回:{0}", echostr);
      try {
        response.getWriter().write(echostr);
        response.getWriter().flush();
        response.getWriter().close();
      } catch (IOException e) {
        LogUtil.error(logger, e, "微信公众号设置url回调处理异常");
      }

    }

  }

  @RequestMapping(value = "/wxcallback", method = RequestMethod.POST)
  public void callback(HttpServletRequest request, HttpServletResponse response) {
    ServletRequest tempRequest = new BodyReaderHttpServletRequestWrapper(request);
    String body = HttpHelper.getBodyString(tempRequest);
    String signature = request.getParameter("signature");
    String timestamp = request.getParameter("timestamp");
    String nonce = request.getParameter("nonce");
    LogUtil.info(logger, "signature:{0}, timestamp:{1}, nonce:{2}",
        signature, timestamp, nonce);
    LogUtil.info(logger, "wx回调数据：{0}", JSON.toJSONString(body));




    /*if (StringUtils.isEmpty(data)) {
      LogUtil.error(logger, "wx回调通知请求参数为空");
      return "{\"code\":101}";
    }*/
    try {
      XmlMapper mapper = new XmlMapper();
      WxCallbackMsgBody wxCallbackMsgBody = mapper.readValue(body, WxCallbackMsgBody.class);
      LogUtil.info(logger, "wxCallbackMsgBody:{0}", JSON.toJSONString(wxCallbackMsgBody));
      // 目前只处理关注/取关事件消息，其他忽略
      boolean rst = false;
      if ("event".equals(wxCallbackMsgBody.getMsgType())) {
        if ("subscribe".equals(wxCallbackMsgBody.getEvent())) {
          rst = wxAccountService.followGzh(wxCallbackMsgBody.getFromUserName());
          LogUtil.info(logger, "关注公众号事件处理结果为{0}，openid:{1}",
              rst, wxCallbackMsgBody.getFromUserName());
        } else if ("unsubscribe".equals(wxCallbackMsgBody.getEvent())) {
          rst = wxAccountService.unFollowGzh(wxCallbackMsgBody.getFromUserName());
          LogUtil.info(logger, "取消关注公众号事件处理结果为{0}，openid:{1}",
              rst, wxCallbackMsgBody.getFromUserName());
        } else {
          LogUtil.info(logger, "非关注/取关事件暂不做处理");
        }
      } else {
        LogUtil.info(logger, "非事件类消息暂不做处理");
      }
    } catch (Exception e) {
      LogUtil.error(logger, e, "wx回调通知处理异常", null);
    }

    try {
      response.getWriter().write("success");
      response.getWriter().flush();
      response.getWriter().close();
    } catch (IOException e) {
      LogUtil.error(logger, e, "wx回调处理异常");
    }

  }

}
