package cn.axzo.msg.center.inside.notices.service.impl;

import cn.axzo.basics.common.constant.enums.TableIsDeleteEnum;
import cn.axzo.msg.center.api.request.TemplateRouterReq;
import cn.axzo.msg.center.dal.MessageRouterDao;
import cn.axzo.msg.center.domain.dto.SyncRelationDataDTO;
import cn.axzo.msg.center.domain.dto.SyncRouterDataDTO;
import cn.axzo.msg.center.domain.entity.MessageRouter;
import cn.axzo.msg.center.domain.enums.MsgRouteTypeEnum;
import cn.axzo.msg.center.inside.notices.service.MessageRouterService;
import cn.hutool.core.collection.CollectionUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 消息路由配置信息(MessageRouter)表服务实现类
 *
 * @author zhangran
 * @since 2022-03-28 14:59:16
 */
@Service
@Slf4j
public class MessageRouterServiceImpl implements MessageRouterService {

  @Resource
  private MessageRouterDao routerDao;

  @Override
  public void saveOrUpdateRouters(List<MessageRouter> routerList) {
    routerDao.saveOrUpdateBatch(routerList);
  }

  @Override
  public List<MessageRouter> listRoutersByRelationIds(Set<Long> relationIds) {
    if(CollectionUtils.isEmpty(relationIds)){
      return new ArrayList<>();
    }
    return routerDao.listRoutersByRelationIds(relationIds);
  }

  @Override
  public void updateRouters(Set<TemplateRouterReq> routers, Long relationId) {
    List<MessageRouter> inDBRouters = getRoutersByRelationId(relationId);
    if (CollectionUtils.isEmpty(routers)) {
      if (CollectionUtils.isEmpty(inDBRouters)) {
        return;
      } else {
        List<Long> removeIds = inDBRouters.stream().map(MessageRouter::getId)
            .collect(Collectors.toList());
        routerDao.removeByIds(removeIds);
        return;
      }

    }

    List<MessageRouter> addRouters = new ArrayList<>();
    List<MessageRouter> updateRouters = new ArrayList<>();
    routers.forEach(i -> {
      MessageRouter router = new MessageRouter();
      router.setRouterType(MsgRouteTypeEnum.getRouteType(i.getType()));
      router.setRouterUrl(i.getUrl());
      if (Objects.isNull(i.getId())) {
        router.setRelationId(relationId);
        addRouters.add(router);
      } else {
        router.setId(i.getId());
        updateRouters.add(router);
      }
    });
    routerDao.updateBatchById(updateRouters);
    routerDao.saveBatch(addRouters);

    // 移除被删除的路由
    if (!CollectionUtils.isEmpty(inDBRouters)) {
      List<Long> aliveIds = routers.stream().map(TemplateRouterReq::getId)
          .collect(Collectors.toList());
      List<Long> removeIds = inDBRouters.stream().filter(i -> !aliveIds.contains(i.getId()))
          .map(MessageRouter::getId).collect(Collectors.toList());
      routerDao.removeByIds(removeIds);
    }
  }

  @Override
  public List<MessageRouter> getRoutersByRelationId(Long relationId) {
    return routerDao.lambdaQuery().eq(MessageRouter::getRelationId, relationId)
        .eq(MessageRouter::getIsDelete, TableIsDeleteEnum.NORMAL.value)
        .list();
  }

  @Override
  public void batchRemoveByIds(List<MessageRouter> routerList) {
    List<Long> ids = routerList.stream().map(MessageRouter::getId).collect(Collectors.toList());
    if (!CollectionUtils.isEmpty(ids)) {
      routerDao.removeByIds(ids);
    }
  }

  @Override
  public List<MessageRouter> getRouterMapByRelationIds(List<Long> relationIds) {
    return routerDao.lambdaQuery().in(MessageRouter::getRelationId, relationIds)
        .eq(MessageRouter::getIsDelete, TableIsDeleteEnum.NORMAL.value)
        .list();
  }

  @Override
  public void syncData(SyncRelationDataDTO routerReq) {
    List<SyncRouterDataDTO> routers = routerReq.getRouters();
    List<Long> routerIds = null;
    if(CollectionUtils.isEmpty(routers)){
      routerIds=new ArrayList<>();
    }else {
      routerIds=routers.stream().map(SyncRouterDataDTO::getId)
              .collect(Collectors.toList());
    }
    List<Long> inDbRouterIds = routerDao.lambdaQuery().eq(MessageRouter::getRelationId, routerReq.getId())
            .list().stream().map(MessageRouter::getId).collect(Collectors.toList());

    Collection<Long> deleteIds = CollectionUtil.subtract(inDbRouterIds, routerIds);
    routerDao.removeByIds(deleteIds);
    if(!CollectionUtils.isEmpty(routers)) {
      List<MessageRouter> updates = new ArrayList<>();
      routers.stream().filter(i -> inDbRouterIds.contains(i.getId())).forEach(i -> {
        MessageRouter router = new MessageRouter();
        router.setId(i.getId());
        router.setRouterType(MsgRouteTypeEnum.getRouteType(i.getRouterType()));
        router.setRouterUrl(i.getRouterUrl());
        router.setRelationId(i.getRelationId());
        updates.add(router);
      });
      routerDao.updateBatchById(updates);

      List<SyncRouterDataDTO> adds = new ArrayList<>();
      routers.stream().filter(i -> !inDbRouterIds.contains(i.getId())).forEach(adds::add);
      routerDao.insertBatchSql(adds);
    }
  }
}
