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.query.MessageRedoQuery;
import cn.axzo.msg.center.notices.common.domain.MessageContext;
import cn.axzo.msg.center.notices.common.enums.MessageStatusEnum;
import cn.axzo.msg.center.notices.common.enums.RetryingFlagEnum;
import cn.axzo.msg.center.notices.common.lang.Page;
import cn.axzo.msg.center.notices.manager.api.MessageRedoManger;
import cn.axzo.msg.center.notices.manager.api.dto.request.MessageRedoQueryRequestDto;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.StringUtils;

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

/**
 * 消息重试
 * @author szg
 */
@Service("messageRedoManger")
public class MessageRedoMangerImpl implements MessageRedoManger {

  @Resource
  private MNSMessageDao mnsMessageDao;

  @Resource
  private MNSMessageRedoDao mnsMessageRedoDao;

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

  @Override
  public Page<MNSMessageRedo> queryPageByMessageRedoQueryRequestDto(MessageRedoQueryRequestDto requestDto) {
    MessageRedoQuery query = new MessageRedoQuery();
    BeanUtils.copyProperties(requestDto, query);
    IPage<MNSMessageRedo> messagePage = mnsMessageRedoDao.queryByPage(query);
    if (messagePage == null) {
      return null;
    }
    Page<MNSMessageRedo> result = new Page<>();
    result.setPageNum(messagePage.getCurrent());
    result.setPageSize(messagePage.getSize());
    result.setTotalElements(messagePage.getTotal());
    result.setList(messagePage.getRecords());
    return result;
  }

  @Override
  public MNSMessageRedo queryMessageRedoByRedoOrderNoAndPhoneNumber(String redoOrderNo, String bizId, String phoneNumber) {
    return mnsMessageRedoDao.lambdaQuery()
        .eq(!StringUtils.isEmpty(redoOrderNo), MNSMessageRedo::getRedoOrderNo,redoOrderNo)
        .eq(!StringUtils.isEmpty(bizId), MNSMessageRedo::getChannelBizId,bizId)
        .eq(MNSMessageRedo::getTargetAddress,phoneNumber)
        .eq(MNSMessageRedo::getIsDelete,0)
        .one();
  }

  @Override
  public boolean updateMessageRedoStatusById(Long id, String oldStatus, String newStatus) {
    mnsMessageRedoDao.lambdaUpdate()
        .set(MNSMessageRedo::getStatus,newStatus)
        .eq(MNSMessageRedo::getStatus,oldStatus)
        .eq(MNSMessageRedo::getId,id)
        .eq(MNSMessageRedo::getIsDelete,0)
        .update();
    return false;
  }

  @Override
  public void saveByMessage(MNSMessage message) {
    MNSMessageRedo messageRedo = new MNSMessageRedo();
    messageRedo.setAppNo(message.getAppNo());
    messageRedo.setRequestNo(message.getRequestNo());
    messageRedo.setMessageOrderNo(message.getMessageOrderNo());
    messageRedo.setRedoOrderNo(message.getChannelCode());
    messageRedo.setMessageType(message.getMessageType());
    messageRedo.setNotifyType(message.getNotifyType());
    messageRedo.setStatus(MessageStatusEnum.INIT.getCode());
    messageRedo.setChannelCode(message.getChannelCode());
    messageRedo.setChannelName(message.getChannelName());
    messageRedo.setTemplateNo(message.getTemplateNo());
    messageRedo.setSubject(message.getSubject());
    messageRedo.setTargetAddress(message.getTargetAddress());
    messageRedo.setRetryingFlag(RetryingFlagEnum.N.name());
    messageRedo.setRetryCount(0);
    messageRedo.insert();
  }

  @Override
  public boolean lockMessage(MessageContext context, Long id) {
    Integer retryCount = context.getRetryCount() + 1;
    context.setRetryCount(retryCount);
    return mnsMessageRedoDao.lambdaUpdate()
        .set(MNSMessageRedo::getRetryCount, retryCount)
        .set(MNSMessageRedo::getRetryingFlag, RetryingFlagEnum.N.name())
        .eq(MNSMessageRedo::getId, id).update();
  }

  @Override
  public boolean updateRetry(Date retryAt, Long id) {
    return mnsMessageRedoDao.lambdaUpdate()
        .set(MNSMessageRedo::getRetryAt, retryAt)
        .set(MNSMessageRedo::getRetryingFlag, RetryingFlagEnum.Y.name())
        .eq(MNSMessageRedo::getId, id)
        .update();
  }

  @Override
  public boolean updateExceptionToFail(Long id, String messageOrderNo) {
    return transactionTemplate.execute(status -> {
      mnsMessageRedoDao.updateExceptionToFail(id);
      return mnsMessageDao.updateExceptionToFail(messageOrderNo);
    });
  }

  @Override
  public boolean updateMessageRedoChannelById(Long id, String bizId,String redoMessageNo) {
    return mnsMessageRedoDao.lambdaUpdate()
        .set(MNSMessageRedo::getChannelBizId, bizId)
        .set(MNSMessageRedo::getRedoOrderNo,redoMessageNo)
        .eq(MNSMessageRedo::getId, id)
        .eq(MNSMessageRedo::getIsDelete,0)
        .update();
  }

}
