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

import cn.axzo.msg.center.dal.MNSMessageDao;
import cn.axzo.msg.center.dal.MNSMessageRedoDao;
import cn.axzo.msg.center.domain.entity.MNSMessage;
import cn.axzo.msg.center.domain.entity.MNSMessageRedo;
import cn.axzo.msg.center.domain.persistence.BaseEntity;
import cn.axzo.msg.center.domain.query.MessageQuery;
import cn.axzo.msg.center.notices.common.enums.MessageStatusEnum;
import cn.axzo.msg.center.notices.common.lang.Page;
import cn.axzo.msg.center.notices.manager.api.MessageManager;
import cn.axzo.msg.center.notices.manager.api.dto.request.MessageQueryRequestDto;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Objects;

/**
 * 消息记录管理实现类
 *
 * @author zhaoyong_sh
 * @see MessageManagerImpl
 * @since 2021-05-19 18:04
 */
@Service("messageManager")
public class MessageManagerImpl implements MessageManager {

  @Resource
  private MNSMessageDao mnsMessageDao;

  @Resource
  private MNSMessageRedoDao mnsMessageRedoDao;

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

  @Override
  public Page<MNSMessage> queryPageByMessageQueryRequestDto(MessageQueryRequestDto requestDto) {
    MessageQuery query = new MessageQuery();
    BeanUtils.copyProperties(requestDto, query);
    IPage<MNSMessage> messagePage = mnsMessageDao.queryByPage(query);
    if (messagePage == null) {
      return null;
    }
    Page<MNSMessage> result = new Page<>();
    result.setPageNum(messagePage.getCurrent());
    result.setPageSize(messagePage.getSize());
    result.setTotalElements(messagePage.getTotal());
    result.setList(messagePage.getRecords());
    return result;
  }

  @Override
  public boolean saveMessage(MNSMessage message) {
    return mnsMessageDao.save(message);
  }

  @Override
  public boolean saveMessageRedo(MNSMessageRedo messageRedo) {
    return mnsMessageRedoDao.save(messageRedo);
  }

  @Override
  public boolean updateToProcessing(String bizId, String requestId, Long id) {
    return mnsMessageDao.lambdaUpdate()
        .set(StringUtils.isNoneBlank(bizId), MNSMessage::getChannelBizId, bizId)
        .set(StringUtils.isNoneBlank(requestId), MNSMessage::getChannelRequestId, requestId)
        .set(MNSMessage::getStatus, MessageStatusEnum.PROCESSING.getCode())
        .set(MNSMessage::getUpdateAt, new Date())
        .eq(MNSMessage::getId, id)
        .eq(MNSMessage::getStatus, MessageStatusEnum.INIT.getCode())
        .update();
  }

  @Override
  public boolean updateToFail(Long id) {
    return mnsMessageDao.lambdaUpdate()
        .set(MNSMessage::getStatus, MessageStatusEnum.FAIL.getCode())
        .set(MNSMessage::getUpdateAt, new Date())
        .eq(MNSMessage::getId, id)
        .eq(MNSMessage::getStatus, MessageStatusEnum.INIT.getCode())
        .update();
  }

  @Override
  public boolean updateToException(MNSMessageRedo messageRedo, Long id) {
    return transactionTemplate.execute(status -> {
      mnsMessageDao.channelException(id);
      return mnsMessageRedoDao.save(messageRedo);
    });
  }

  @Override
  public boolean updateExceptionToQueryStatus(String targetStatus, Long id) {
    return mnsMessageDao.lambdaUpdate().eq(MNSMessage::getId, id)
        .eq(MNSMessage::getStatus, MessageStatusEnum.EXCEPTION.getCode())
        .set(MNSMessage::getStatus, targetStatus)
        .update();
  }


  @Override
  public MNSMessage queryMessageByMessageOrderNoAndPhoneNumber(String messageOrderNo, String channelBizId,
                                                               String phoneNumber) {
    return mnsMessageDao.lambdaQuery()
        .eq(Objects.nonNull(messageOrderNo), MNSMessage::getMessageOrderNo, messageOrderNo)
        .eq(Objects.nonNull(channelBizId), MNSMessage::getChannelBizId, channelBizId)
        .eq(MNSMessage::getTargetAddress, phoneNumber)
        .eq(MNSMessage::getIsDelete, 0)
        .one();
  }

  @Override
  public boolean updateProcessingMessageStatusById(Long id, String status) {
    return mnsMessageDao
        .lambdaUpdate()
        .eq(MNSMessage::getId, id)
        .eq(MNSMessage::getIsDelete, 0)
        .eq(MNSMessage::getStatus,MessageStatusEnum.PROCESSING.getCode())
        .set(MNSMessage::getStatus, status)
        .update();
  }

  @Override
  public boolean updateMessageStatusByMessageOrderNo(String messageOrderNo, String status) {
    return mnsMessageDao
        .lambdaUpdate()
        .eq(MNSMessage::getMessageOrderNo, messageOrderNo)
        .eq(MNSMessage::getIsDelete, 0)
        .set(MNSMessage::getStatus, status)
        .update();
  }

  @Override
  public boolean updateToSuccess(String bizId, String requestId, Long id) {
    return mnsMessageDao.lambdaUpdate()
        .set(StringUtils.isNoneBlank(bizId), MNSMessage::getChannelBizId, bizId)
        .set(StringUtils.isNoneBlank(requestId), MNSMessage::getChannelRequestId, requestId)
        .set(MNSMessage::getStatus, MessageStatusEnum.SUCCESS.getCode())
        .set(BaseEntity::getUpdateAt, new Date())
        .eq(BaseEntity::getId, id)
        .eq(MNSMessage::getStatus, MessageStatusEnum.INIT.getCode())
        .update();
  }

}
