package cn.axzo.msg.center.notices.manager;

import cn.axzo.msg.center.dal.MNSBatchMessageDao;
import cn.axzo.msg.center.dal.MNSBatchMessageRequestDao;
import cn.axzo.msg.center.domain.dto.BatchMessageStatisticsResponseDto;
import cn.axzo.msg.center.domain.entity.MNSBatchMessage;
import cn.axzo.msg.center.domain.entity.MNSBatchMessageRequest;
import cn.axzo.msg.center.domain.query.BatchMessageRequestQuery;
import cn.axzo.msg.center.notices.common.enums.BatchMessageRequestStatusEnum;
import cn.axzo.msg.center.notices.common.enums.BatchMessageStatusEnum;
import cn.axzo.msg.center.notices.common.lang.Page;
import cn.axzo.msg.center.notices.manager.api.BatchMessageRequestManger;
import cn.axzo.msg.center.notices.manager.api.dto.request.BatchMessageRequestDto;
import cn.axzo.msg.center.notices.manager.api.dto.request.SmsContentDto;
import cn.azxo.framework.common.utils.LogUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Classname BatchMessageRequestMangerImpl
 * @Author: szg
 * @Date: 2021年08月09日 14:10
 * @Description:
 */
@RefreshScope
@Service("batchMessageRequestManger")
@Slf4j
public class BatchMessageRequestMangerImpl implements BatchMessageRequestManger {

  @Resource
  private MNSBatchMessageRequestDao mnsBatchMessageRequestDao;

  @Resource
  private MNSBatchMessageDao mnsBatchMessageDao;

  @Resource(name = "transactionTemplate")
  private TransactionTemplate transactionTemplate;

  @Value("${batch.request.splitSize:100}")
  private Integer splitSize;

  @Override
  public boolean saveBatchMessageRequest(MNSBatchMessageRequest batchMessageRequest) {
    return mnsBatchMessageRequestDao.save(batchMessageRequest);
  }

  @Override
  public Page<MNSBatchMessageRequest> queryPageByBatchMessageQueryRequestDto(
      BatchMessageRequestDto requestDto) {
    BatchMessageRequestQuery query = new BatchMessageRequestQuery();
    BeanUtils.copyProperties(requestDto, query);
    IPage<MNSBatchMessageRequest> messagePage = mnsBatchMessageRequestDao.queryByPage(query);
    if (messagePage == null) {
      return null;
    }
    Page<MNSBatchMessageRequest> result = new Page<>();
    result.setPageNum(messagePage.getCurrent());
    result.setPageSize(messagePage.getSize());
    result.setTotalElements(messagePage.getTotal());
    result.setList(messagePage.getRecords());
    return result;
  }

  @Override
  public List<String> batchMessageRequestSplitAndSave(MNSBatchMessageRequest batchMessageRequest) {

    String smsContent = batchMessageRequest.getSmsContent();
    if (StringUtils.isEmpty(smsContent)) {
      log.info("BatchMessageRequestMangerImpl.batchMessageRequestSplitAndSave smsContent is null");
      return Lists.newArrayList();
    }
    List<SmsContentDto> totalList = JSON.parseArray(smsContent, SmsContentDto.class);
    if (CollectionUtils.isEmpty(totalList)) {
      log.info("BatchMessageRequestMangerImpl.batchMessageRequestSplitAndSave totalList is null");
      return Lists.newArrayList();
    }
    List<List<SmsContentDto>> split = ListUtil.split(totalList, splitSize);
    //保存batch_message
    List<MNSBatchMessage> batchMessageList = new ArrayList<>();
    for (List<SmsContentDto> dtoList : split) {
      if (CollectionUtils.isEmpty(dtoList)) {
        log.info("BatchMessageRequestMangerImpl.batchMessageRequestSplitAndSave split is null");
        continue;
      }
      MNSBatchMessage batchMessage = buildBatchMessage(batchMessageRequest, dtoList);
      batchMessageList.add(batchMessage);
    }

    boolean result = transactionTemplate.execute(status ->{
      boolean updateRes = mnsBatchMessageRequestDao.updateStatusById(batchMessageRequest.getId(),
          BatchMessageRequestStatusEnum.SPLIT_COMPLETED.getCode());
      if (updateRes){
        return mnsBatchMessageDao.saveBatch(batchMessageList);
      }
      return false;
    });

    if(result) {
      return batchMessageList.stream().map(v -> v.getBatchNo()).collect(Collectors.toList());
    }

    return Lists.newArrayList();
  }

  @Override
  public MNSBatchMessageRequest queryBatchMessage(String appCode, String requestNo) {
    return mnsBatchMessageRequestDao.queryBatchMessage(appCode, requestNo);
  }

  @Override
  public boolean updateRequestSuccess(String remark, Long id) {
    return mnsBatchMessageRequestDao.updateRequestSuccess(remark, id);
  }

  @Override
  public void handleBatchMessageRequestStatistics(MNSBatchMessageRequest request) {
    if (Objects.isNull(request)) {
      LogUtil.error("批次处理完成消息 handleBatchMessageRequestInfoUpdate batchMessageRequest is null");
      return;
    }
    // 统计 batch_message
    BatchMessageStatisticsResponseDto responseDto = mnsBatchMessageDao
        .getStatisticsMessageInfo(request.getAppNo(), request.getRequestNo());

    if (Objects.isNull(responseDto)) {
      LogUtil.error(
          "批次处理完成消息 handleBatchMessageRequestInfoUpdate 统计 BatchMessageStatisticsResponseDto is null");
      return;
    }

    //batchMessageRequest状态处理
    Integer batchMessageRequestStatus = getBatchMessageRequestStatus(request,
        responseDto);
    //更新此次统计
    mnsBatchMessageRequestDao
        .updateBatchMessageRequestInfoById(request.getId(), batchMessageRequestStatus,
            responseDto.getSuccessCount(), responseDto.getFailCount());
  }

  /**
   * 构建批量消息
   * @param batchMessageRequest
   * @param dtoList
   * @return
   */
  private MNSBatchMessage buildBatchMessage(MNSBatchMessageRequest batchMessageRequest,
                                            List<SmsContentDto> dtoList) {
    MNSBatchMessage batchMessage = new MNSBatchMessage();
    batchMessage.setAppNo(batchMessageRequest.getAppNo());
    batchMessage.setRequestNo(batchMessageRequest.getRequestNo());
    batchMessage.setBatchNo(IdUtil.simpleUUID());
    batchMessage.setTemplateNo(batchMessageRequest.getTemplateNo());
    batchMessage.setMessageOrderNo(IdUtil.simpleUUID());
    batchMessage.setSmsContent(JSON.toJSONString(dtoList));
    batchMessage.setBatchSize(dtoList.size());
    batchMessage.setSendType(batchMessageRequest.getSendType());
    batchMessage.setStatus(BatchMessageStatusEnum.INITIALIZE.getCode());
    batchMessage.setChannelMsgId("");
    batchMessage.setChannelCode("");
    batchMessage.setChannelErrorMsg("");
    return batchMessage;
  }

  /**
   * 获取状态
   * @param batchMessageRequest
   * @param responseDto
   * @return
   */
  private Integer getBatchMessageRequestStatus(MNSBatchMessageRequest batchMessageRequest,
                                               BatchMessageStatisticsResponseDto responseDto) {
    Integer batchMessageRequestStatus = BatchMessageRequestStatusEnum.PARTIAL_SUCCESS.getCode();
    //处理状态
    if (Objects.equals(batchMessageRequest.getTotalSize(), responseDto.getSuccessCount())) {
      batchMessageRequestStatus = BatchMessageRequestStatusEnum.SEND_SUCCESS.getCode();
    } else if (Objects.equals(batchMessageRequest.getTotalSize(), responseDto.getFailCount())) {
      batchMessageRequestStatus = BatchMessageRequestStatusEnum.ALL_FAILED.getCode();
    }
    return batchMessageRequestStatus;
  }

}
