package com.seer.teach.mp.factory;

import cn.hutool.core.lang.Assert;
import com.binarywang.spring.starter.wxjava.mp.properties.WxMpProperties;
import com.google.common.collect.Maps;
import com.seer.teach.mp.entity.MpAccountEntity;
import com.seer.teach.mp.handler.LocationHandler;
import com.seer.teach.mp.handler.MessageReceiveHandler;
import com.seer.teach.mp.handler.SubscribeHandler;
import com.seer.teach.mp.handler.UnsubscribeHandler;
import com.seer.teach.mp.service.IMpAccountService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.redis.RedisTemplateWxRedisOps;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.WxMpTemplateMsgService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.config.impl.WxMpRedisConfigImpl;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;

@Slf4j
@RequiredArgsConstructor
public class MpServiceFactory {

    /**
     * 微信 appId 与 WxMpService 的映射
     */
    private volatile Map<String, WxMpService> appId2MpServices;

    /**
     * 公众号账号 id 与 WxMpService 的映射
     */
    private volatile Map<Integer, WxMpService> id2MpServices;

    /**
     * 微信 appId 与 WxMpMessageRouter 的映射
     */
    private volatile Map<String, WxMpMessageRouter> mpMessageRouters;

    private final RedisTemplateWxRedisOps redisTemplateWxRedisOps;

    private final IMpAccountService mpAccountService;

    private final WxMpProperties mpProperties;
    private final MessageReceiveHandler messageReceiveHandler;
    private final SubscribeHandler subscribeHandler;
    private final UnsubscribeHandler unsubscribeHandler;
    private final LocationHandler locationHandler;

    public void init() {
        List<MpAccountEntity> accounts = mpAccountService.list();
        log.info("[initLocalCache][缓存公众号账号，数量为:{}]", accounts.size());
        if (CollectionUtils.isEmpty( accounts)){
            return;
        }
        Map<String, WxMpService> appId2MpServices = Maps.newHashMap();
        Map<Integer, WxMpService> id2MpServices = Maps.newHashMap();
        Map<String, WxMpMessageRouter> mpMessageRouters = Maps.newHashMap();
        accounts.forEach(account -> {
            // 构建 WxMpService 对象
            WxMpService mpService = buildMpService(account);
            appId2MpServices.put(account.getAppId(), mpService);
            id2MpServices.put(account.getId(), mpService);
            // 构建 WxMpMessageRouter 对象
            WxMpMessageRouter mpMessageRouter = buildMpMessageRouter(mpService);
            mpMessageRouters.put(account.getAppId(), mpMessageRouter);
        });

        // 设置到缓存
        this.appId2MpServices = appId2MpServices;
        this.id2MpServices = id2MpServices;
        this.mpMessageRouters = mpMessageRouters;
    }

    public WxMpService getRequiredMpService(Integer id) {
        return getMpService(id);
    }

    public WxMpService getRequiredMpService(String appId) {
        return getMpService(appId);
    }

    public WxMpService getMpService(Integer id) {
        return id2MpServices.get(id);
    }

    public WxMpService getMpService(String appId) {
        return appId2MpServices.get(appId);
    }

    /**
     * 获取 WxMpTemplateMsgService
     *
     * @param appId 微信公众号 appId
     * @return WxMpTemplateMsgService
     */
    public WxMpTemplateMsgService getWxMpTemplateMsgService(String appId) {
        return appId2MpServices.get(appId).getTemplateMsgService();
    }


    public WxMpMessageRouter getMpMessageRouter(String appId) {
        return mpMessageRouters.get(appId);
    }

    public WxMpMessageRouter getRequiredMpMessageRouter(String appId) {
        WxMpMessageRouter wxMpMessageRouter = getMpMessageRouter(appId);
        Assert.notNull(wxMpMessageRouter, "找到对应 appId({}) 的 WxMpMessageRouter，请核实！", appId);
        return wxMpMessageRouter;
    }

    private WxMpService buildMpService(MpAccountEntity account) {
        WxMpRedisConfigImpl configStorage = new WxMpRedisConfigImpl(
                redisTemplateWxRedisOps, mpProperties.getConfigStorage().getKeyPrefix());
        configStorage.setAppId(account.getAppId());
        configStorage.setSecret(account.getAppSecret());
        configStorage.setToken(account.getToken());
        configStorage.setAesKey(account.getAesKey());

        WxMpService service = new WxMpServiceImpl();
        service.setWxMpConfigStorage(configStorage);
        return service;
    }

    private WxMpMessageRouter buildMpMessageRouter(WxMpService mpService) {
        WxMpMessageRouter router = new WxMpMessageRouter(mpService);
        // 记录所有事件的日志
        router.rule().handler(messageReceiveHandler).next();

        // 关注事件
        router.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.EventType.SUBSCRIBE).handler(subscribeHandler)
                .end();

        // 取消关注事件
        router.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.EventType.UNSUBSCRIBE)
                .handler(unsubscribeHandler)
                .end();

        // 上报地理位置事件
        router.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.EventType.LOCATION).handler(locationHandler)
                .end();

        // 接收地理位置消息
        router.rule().async(false).msgType(WxConsts.XmlMsgType.LOCATION)
                .handler(locationHandler).end();

        return router;
    }
}