package com.xunhong.erp.turbo.facade.app.executor.cmd;

import com.xunhong.erp.turbo.api.facade.dto.cmd.WxMpCallbackCmd;
import com.xunhong.erp.turbo.api.infra.api.SettingServiceI;
import com.xunhong.erp.turbo.facade.app.executor.common.WxCmdExe;
import com.xunhong.erp.turbo.facade.app.executor.handler.SubscribeHandler;
import com.xunhong.erp.turbo.facade.app.executor.handler.UnsubscribeHandler;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Component;

import static me.chanjar.weixin.common.api.WxConsts.EventType.SUBSCRIBE;
import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType.EVENT;
import static me.chanjar.weixin.cp.constant.WxCpConsts.SchoolContactChangeType.UNSUBSCRIBE;

@Slf4j
@Component
@RequiredArgsConstructor
public class WxMpCallbackCmdExe extends WxCmdExe {

	@DubboReference(version = "1.0.0")
	private final SettingServiceI settingService;

	private final SubscribeHandler subscribeHandler;

	private final UnsubscribeHandler unsubscribeHandler;

	private WxMpMessageRouter router;

	public String execute(WxMpCallbackCmd wxMpCallbackCmd) {
		WxMpService wxMpService = getWxMpService(settingService);

		boolean checkSignature = wxMpService.checkSignature(wxMpCallbackCmd.getTimestamp(), wxMpCallbackCmd.getNonce(), wxMpCallbackCmd.getSignature());
		if (!checkSignature) {
			return "非法请求";
		}

		if (wxMpCallbackCmd.getEchostr() != null) {
			return wxMpCallbackCmd.getEchostr();
		}

		this.refreshRouter(wxMpService);

		String out = null;
		String encType = wxMpCallbackCmd.getEncType();
		if (encType == null) {
			// 明文传输的消息
			WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(wxMpCallbackCmd.getRequestBody());
			WxMpXmlOutMessage outMessage = this.route(inMessage);
			if (outMessage == null) {
				return "";
			}

			out = outMessage.toXml();
		} else if ("aes".equals(encType)) {
			// aes加密的消息
			WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(
				wxMpCallbackCmd.getRequestBody(),
				wxMpService.getWxMpConfigStorage(),
				wxMpCallbackCmd.getTimestamp(),
				wxMpCallbackCmd.getNonce(),
				wxMpCallbackCmd.getMsgSignature()
			);

			log.debug("\n消息解密后内容为：\n{} ", inMessage.toString());
			WxMpXmlOutMessage outMessage = this.route(inMessage);
			if (outMessage == null) {
				return "";
			}

			out = outMessage.toEncryptedXml(wxMpService.getWxMpConfigStorage());
		}

		log.debug("\n组装回复信息：{}", out);

		return out;
	}

	public WxMpXmlOutMessage route(WxMpXmlMessage message) {
		try {
			return this.router.route(message);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}

		return null;
	}


	private void refreshRouter(WxMpService wxMpService) {
		final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService);

		// 关注事件
		newRouter.rule().async(false).msgType(EVENT).event(SUBSCRIBE).handler(this.subscribeHandler).end();
		// 取消关注事件
		newRouter.rule().async(false).msgType(EVENT).event(UNSUBSCRIBE).handler(this.unsubscribeHandler).end();

		this.router = newRouter;
	}
}
