package com.fs.task;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.fs.store.domain.FsMiniprogramSubNotifyTask;
import com.fs.store.dto.ClientCredGrantReqDTO;
import com.fs.store.dto.MiniGramSubsMsgResultDTO;
import com.fs.store.dto.TemplateMessageSendRequestDTO;
import com.fs.store.dto.WeXinAccessTokenDTO;
import com.fs.store.enums.MiniAppNotifyTaskStatusEnum;
import com.fs.store.mapper.FsMiniprogramSubNotifyTaskMapper;
import com.fs.store.service.IWechatMiniProgrService;
import com.fs.wx.miniapp.config.WxMaProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * 小程序订阅通知定时任务
 */
@Service("miniProgramSubTask")
@Slf4j
@RequiredArgsConstructor
public class MiniProgramSubTask {
    private final IWechatMiniProgrService wechatMiniProgrService;

    private final FsMiniprogramSubNotifyTaskMapper notifyTaskMapper;

    private WxMaProperties.Config config = null;

    @Autowired
    public void setConfig(WxMaProperties properties) {
        if(ObjectUtil.isNotNull(properties)){
            this.config = properties.getConfigs().get(0);
        }
    }

    /**
     * 小程序订阅通知
     */
    public void notifyMiniAppSub(){
        log.info("小程序订阅通知定时任务");
        // 先获取所有可用待处理任务
        List<FsMiniprogramSubNotifyTask> pendingData = notifyTaskMapper.selectPendingData();
        if(CollectionUtils.isEmpty(pendingData)){
            log.info("小程序订阅通知定时任务, 无待处理数据");
            return;
        }
        for (FsMiniprogramSubNotifyTask pendingDatum : pendingData) {
            pendingDatum.setUpdateTime(LocalDateTime.now());

            ClientCredGrantReqDTO clientCredGrantReqDTO = new ClientCredGrantReqDTO();
            clientCredGrantReqDTO.setAppid(config.getAppid());
            clientCredGrantReqDTO.setSecret(config.getSecret());
            clientCredGrantReqDTO.setGrant_type("client_credential");

           try{
               // 获取accessToken
               WeXinAccessTokenDTO stableToken = wechatMiniProgrService
                       .getStableToken(clientCredGrantReqDTO);

               String accessToken = stableToken.getAccessToken();

               // 调用微信小程序订阅通知
               TemplateMessageSendRequestDTO sendRequestDTO = new TemplateMessageSendRequestDTO();
               sendRequestDTO.setTemplate_id(pendingDatum.getTemplateId());
               sendRequestDTO.setTouser(pendingDatum.getTouser());
               sendRequestDTO.setPage(pendingDatum.getPage());
               TypeReference<Map<String, TemplateMessageSendRequestDTO.TemplateDataValue>> typeReference = new TypeReference<Map<String, TemplateMessageSendRequestDTO.TemplateDataValue>>() {};
               sendRequestDTO.setData(JSONObject.parseObject(pendingDatum.getData(),typeReference));
               MiniGramSubsMsgResultDTO miniGramSubsMsgResultDTO = wechatMiniProgrService.sendSubscribeMsg(accessToken, sendRequestDTO);
               pendingDatum.setRequestBody(JSONObject.toJSONString(sendRequestDTO));
               pendingDatum.setResponseBody(JSONObject.toJSONString(miniGramSubsMsgResultDTO));

               // 如果推送消息成功
               if(miniGramSubsMsgResultDTO.getErrcode() == 0){
                   pendingDatum.setStatus(MiniAppNotifyTaskStatusEnum.SUCCESS.getValue());
               } else {
                   // 更新任务状态为执行失败
                   pendingDatum.setStatus(MiniAppNotifyTaskStatusEnum.FAILED.getValue());
                   pendingDatum.setErrorMessage(JSONObject.toJSONString(miniGramSubsMsgResultDTO));
                   pendingDatum.setRetryCount(pendingDatum.getRetryCount() +1);
               }
           }catch (Throwable e){
               // 更新任务状态为执行失败
               pendingDatum.setStatus(MiniAppNotifyTaskStatusEnum.FAILED.getValue());
               pendingDatum.setErrorMessage(ExceptionUtils.getStackTrace(e));
               pendingDatum.setRetryCount(pendingDatum.getRetryCount() +1);
               log.error("小程序订阅通知定时任务异常: {}", ExceptionUtils.getStackTrace(e));
           }
        }

        if(CollectionUtils.isNotEmpty(pendingData)){
            notifyTaskMapper.updateBatchById(pendingData);
        }

    }
}
