package cn.com.poc.user.wecom.rest.impl;

import cn.com.poc.common.service.RedisService;
import cn.com.poc.common.utils.StringUtils;
import cn.com.poc.user.wecom.constant.WecomConstant;
import cn.com.poc.user.wecom.domain.properties.WecomProperties;
import cn.com.poc.user.wecom.rest.WecomCallbackRest;
import cn.com.poc.user.wecom.util.WXBizMsgCrypt;
import org.json.JSONObject;
import org.json.XML;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.PrintWriter;

@Component
public class WecomCallbackRestImpl implements WecomCallbackRest {

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

    @Resource
    private WecomProperties wecomProperties;

    @Resource
    private RedisService redisService;

    @Override
    public void commandEvent(HttpServletRequest request, HttpServletResponse response, String msgSignature, String timestamp, String nonce, String data) throws Exception {
        String method = request.getMethod();
        if ("GET".equalsIgnoreCase(method)) {
            handleVerify(response, msgSignature, timestamp, nonce, data);
            return;
        }
        if ("POST".equalsIgnoreCase(method)) {
            handleSuiteTicket(request, response, msgSignature, timestamp, nonce);
        }
    }

    private void handleVerify(HttpServletResponse response, String msgSignature, String timestamp, String nonce, String data) throws Exception {
        PrintWriter writer = response.getWriter();
        WXBizMsgCrypt wxcpt = buildSuiteCrypt();
        String echoStr = wxcpt.VerifyURL(msgSignature, timestamp, nonce, data);
        writer.print(echoStr);
        writer.flush();
    }

    private void handleSuiteTicket(HttpServletRequest request, HttpServletResponse response, String msgSignature, String timestamp, String nonce) throws Exception {
        StringBuilder body = new StringBuilder();
        BufferedReader reader = request.getReader();
        String line;
        while ((line = reader.readLine()) != null) {
            body.append(line);
        }
        WXBizMsgCrypt wxcpt = buildSuiteCrypt();
        String decryptedXml = wxcpt.DecryptMsg(msgSignature, timestamp, nonce, body.toString());
        logger.info("wecom suite callback payload: {}", decryptedXml);
        JSONObject jsonObject = XML.toJSONObject(decryptedXml).getJSONObject("xml");
        String infoType = jsonObject.optString("InfoType");
        if ("suite_ticket".equalsIgnoreCase(infoType)) {
            String suiteId = jsonObject.optString("SuiteId");
            String suiteTicket = jsonObject.optString("SuiteTicket");
            if (StringUtils.isNotBlank(suiteId) && StringUtils.isNotBlank(suiteTicket)) {
                String redisKey = WecomConstant.RedisKey.SUITE_TICKET + ":" + suiteId;
                redisService.set(redisKey, suiteTicket);
                logger.info("stored suite_ticket for suiteId {}", suiteId);
            }
        }
        PrintWriter writer = response.getWriter();
        writer.print("success");
        writer.flush();
    }

    private WXBizMsgCrypt buildSuiteCrypt() throws Exception {
        return new WXBizMsgCrypt(wecomProperties.getToken(), wecomProperties.getEncodingAesKey(), wecomProperties.getSuiteId());
    }
}
