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

import cn.axzo.basics.common.constant.enums.TableIsDeleteEnum;
import cn.axzo.msg.center.api.enums.ReceiveTypeEnum;
import cn.axzo.msg.center.dal.MessageModuleDao;
import cn.axzo.msg.center.domain.dto.CreateModuleDTO;
import cn.axzo.msg.center.domain.dto.MsgModuleDTO;
import cn.axzo.msg.center.domain.dto.SearchModuleDTO;
import cn.axzo.msg.center.domain.dto.SyncModuleDataDTO;
import cn.axzo.msg.center.domain.dto.UpdateModuleDTO;
import cn.axzo.msg.center.domain.entity.MessageModule;
import cn.axzo.msg.center.domain.enums.ModuleBizTypeEnum;
import cn.axzo.msg.center.domain.enums.UserTypeEnum;
import cn.axzo.msg.center.domain.persistence.BaseEntity;
import cn.axzo.msg.center.inside.notices.service.MessageModuleService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

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

/**
 * 消息模块(MessageModule)表服务实现类
 *
 * @author zhangran
 * @since 2022-03-28 14:59:16
 */
@Service
@Slf4j
public class MessageModuleServiceImpl implements MessageModuleService {

  @Resource
  private MessageModuleDao messageModuleDao;


  /**
   * 用户类型获取模块信息
   *
   * @param userTypeEnum
   * @return
   */
  @Override
  public List<MessageModule> listModuleByUserType(UserTypeEnum userTypeEnum) {
    ReceiveTypeEnum receiveTypeEnum = ReceiveTypeEnum.getByMessage(userTypeEnum.getName());
    List<MessageModule> messageModules = messageModuleDao.listMoudleByUserType(ReceiveTypeEnum.valueOf(receiveTypeEnum.getCode()));
    return messageModules;
  }

  @Override
  public List<MsgModuleDTO> listModuleByRelationIdsOrTypeIds(Set<Integer> oldTypeIds,
                                                             Set<Long> relationIds) {
    return messageModuleDao.listModuleByRelationIdsOrTypeIds(oldTypeIds, relationIds);
  }

  @Override
  public List<MessageModule> getAllModules() {
    return messageModuleDao.lambdaQuery().eq(MessageModule::getIsDelete, TableIsDeleteEnum.NORMAL)
        .list();
  }

  @Override
  public MessageModule getModuleById(Long id) {
    return messageModuleDao.getById(id);
  }

  @Override
  public IPage<MessageModule> page(SearchModuleDTO dto) {
    return messageModuleDao.page(dto.toPage(),
        new LambdaQueryWrapper<MessageModule>()
            .eq(Objects.nonNull(dto.getIdentityType()), MessageModule::getOwnedType,
                dto.getIdentityType())
            .eq(Objects.nonNull(dto.getBizType()), MessageModule::getBizType, dto.getBizType())
            .eq(MessageModule::getIsDelete,
               TableIsDeleteEnum.NORMAL.value)
            .orderByDesc(MessageModule::getCreateAt)
    );
  }

  @Override
  public void add(CreateModuleDTO dto) {
    MessageModule mm = new MessageModule();
    mm.setIcon(dto.getIcon());
    mm.setModuleName(dto.getModuleName());
    mm.setOwnedType(dto.getOwnedType());
    mm.setBizType(dto.getBizType());
    mm.setRemark(dto.getModuleName());
    mm.setId(dto.getId());
    messageModuleDao.saveOrUpdate(mm);
  }


  @Override
  public void update(UpdateModuleDTO dto) {
    MessageModule mm = messageModuleDao.getById(dto.getId());
    mm.setIcon(dto.getIcon());
    mm.setModuleName(dto.getModuleName());
    mm.setOwnedType(dto.getOwnedType());
    mm.setBizType(dto.getBizType());
    mm.setRemark(dto.getModuleName());
    messageModuleDao.updateById(mm);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void delete(Long id) {
    messageModuleDao.lambdaUpdate().set(MessageModule::getIsDelete, id)
        .eq(MessageModule::getId, id)
        .update();
  }

  @Override
  public List<MessageModule> getModuleByIds(List<Long> ids) {
    if (CollectionUtils.isEmpty(ids)) {
      return Lists.newArrayList();
    }
    return messageModuleDao.listByIds(ids);
  }


  @Override
  public Map<Integer, List<Long>> listModuleByBizType() {
    // google 的工具,返回的就是普通的HashMap,后续使用不会有任何限制
    Map<Integer, List<Long>> result = Maps.newHashMap();
    List<MessageModule> bizTypeList = messageModuleDao.lambdaQuery()
        .eq(BaseEntity::getIsDelete, TableIsDeleteEnum.NORMAL)
        .select(MessageModule::getBizType)
        .groupBy(MessageModule::getBizType)
        .list();
    if (CollectionUtils.isEmpty(bizTypeList)) {
      return result;
    }

    bizTypeList.forEach(i -> {
      List<Long> ids = messageModuleDao.lambdaQuery()
          .eq(MessageModule::getBizType, ModuleBizTypeEnum.CONSTRUCTION.getCode())
          .eq(MessageModule::getIsDelete, TableIsDeleteEnum.NORMAL.value)
          .list().stream().map(MessageModule::getId).collect(Collectors.toList());
      result.put(i.getBizType().getCode(), ids);
    });
    return result;
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void syncData(List<SyncModuleDataDTO> dtos) {
    List<Long> changeIds = dtos.stream().map(SyncModuleDataDTO::getId).collect(Collectors.toList());
    List<Long> inDbRouterIds = messageModuleDao.listByIds(changeIds).stream()
            .map(MessageModule::getId)
            .collect(Collectors.toList());

    dtos.stream().filter(i -> inDbRouterIds.contains(i.getId())).forEach(i -> {
      MessageModule module = new MessageModule();
      module.setId(i.getId());
      module.setModuleName(i.getModuleName());
      module.setIcon(i.getIcon());
      module.setOwnedType(i.getOwnedType());
      module.setBizType(i.getBizType());
      messageModuleDao.updateById(module);
    });

    List<SyncModuleDataDTO> adds = new ArrayList<>();
    dtos.stream().filter(i -> !inDbRouterIds.contains(i.getId())).forEach(adds::add);
    if(CollectionUtils.isEmpty(adds)){
      return;
    }
    messageModuleDao.insertBatchSql(adds);
  }

  @Override
  public List<MessageModule> listByModuleName(String moduleName) {
    if (StringUtils.isBlank(moduleName)) {
      return Collections.emptyList();
    }
    return getAllModules().stream()
            .filter(e -> Objects.equals(e.getModuleName(), moduleName))
            .collect(Collectors.toList());
  }

  @Override
  public List<Long> listModuleIdByBizType(ModuleBizTypeEnum bizType) {
    if (Objects.isNull(bizType)) {
      log.info("bizType is null.");
      return Collections.emptyList();
    }
    return messageModuleDao.lambdaQuery()
            .eq(MessageModule::getBizType, bizType.getCode())
            .eq(MessageModule::getIsDelete, TableIsDeleteEnum.NORMAL.value)
            .select(MessageModule::getId)
            .list().stream()
            .map(MessageModule::getId)
            .collect(Collectors.toList());
  }
}
