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

import cn.axzo.msg.center.api.request.CreateTemplateReq;
import cn.axzo.msg.center.api.request.UpdateTemplateAudioFileReq;
import cn.axzo.msg.center.api.request.UpdateTemplateReq;
import cn.axzo.msg.center.common.enums.TableIsDeleteEnum;
import cn.axzo.msg.center.dal.MessageRelationDao;
import cn.axzo.msg.center.domain.dto.SearchTemplateDTO;
import cn.axzo.msg.center.domain.dto.SyncRelationDataDTO;
import cn.axzo.msg.center.domain.entity.MessageRelation;
import cn.axzo.msg.center.domain.entity.MessageRouter;
import cn.axzo.msg.center.domain.entity.MessageTemplate;
import cn.axzo.msg.center.domain.enums.MsgRouteTypeEnum;
import cn.axzo.msg.center.domain.persistence.BaseEntity;
import cn.axzo.msg.center.inside.notices.service.MessageRelationService;
import cn.axzo.msg.center.inside.notices.service.MessageRouterService;
import cn.axzo.msg.center.inside.notices.service.MessageTemplateService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

/**
 * 模块与模板的关系表(MessageRelation)表服务实现类
 *
 * @author zhangran
 * @since 2022-03-28 14:59:16
 */
@Service
@Slf4j
public class MessageRelationServiceImpl implements MessageRelationService {

  @Autowired
  private MessageRelationDao messageRelationDao;
  @Autowired
  private MessageTemplateService templateService;
  @Autowired
  private MessageRouterService routerService;

  @Override
  public List<MessageRelation> getAllRelations() {
    return messageRelationDao.lambdaQuery()
        .eq(BaseEntity::getIsDelete, TableIsDeleteEnum.NORMAL.value)
        .list();
  }

  @Override
  public Boolean hasRelationGtUpdateAt(LocalDateTime updateAt) {
    return messageRelationDao.lambdaQuery()
        .gt(Objects.nonNull(updateAt), MessageRelation::getUpdateAt, updateAt)
        .count() > 0;
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void createTemplate(CreateTemplateReq dto) {
    MessageTemplate template = new MessageTemplate();
    template.setTitle(dto.getTitle());
    template.setContent(dto.getContent());
    //template.setId(dto.getTemplateId());
    templateService.saveOrUpdateTemplate(template);

    MessageRelation relation = new MessageRelation();
    relation.setTypeId(0);
    //relation.setId(dto.getRelationIdField());
    relation.setModuleId(dto.getModuleId());
    relation.setTemplateId(template.getId());
    relation.setContactUser(dto.getContactUser());
    messageRelationDao.saveOrUpdate(relation);

    List<MessageRouter> routerList = new ArrayList<>();
    if(!CollectionUtils.isEmpty(dto.getRouters())) {
      dto.getRouters().forEach(r -> {
        MessageRouter router = new MessageRouter();
        router.setId(r.getId());
        router.setRelationId(relation.getId());
        router.setRouterType(MsgRouteTypeEnum.getRouteType(r.getType()));
        router.setRouterUrl(r.getUrl());
        routerList.add(router);
      });
    }
    routerService.saveOrUpdateRouters(routerList);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void updateTemplate(UpdateTemplateReq dto) {
    MessageRelation relation = messageRelationDao.getById(dto.getRelationId());
    MessageTemplate template = templateService.getTemplateById(relation.getTemplateId());
    template.setTitle(dto.getTitle());
    template.setContent(dto.getContent());
    templateService.saveOrUpdateTemplate(template);
    relation.setModuleId(dto.getModuleId());
    relation.setContactUser(dto.getContactUser());
    messageRelationDao.saveOrUpdate(relation);
    routerService.updateRouters(dto.getRouters(), relation.getId());
  }

  @Override
  public IPage<MessageRelation> page(SearchTemplateDTO dto) {
    List<Long> relationIds;
    if(!StringUtils.hasLength(dto.getRelationId())){
      relationIds = new ArrayList<>();
    }else {
      relationIds =Arrays.stream(dto.getRelationId().split(",")).mapToLong(Long::parseLong).boxed().collect(Collectors.toList());
    }
    return messageRelationDao.page(dto.toPage(),
        new LambdaQueryWrapper<MessageRelation>()
            .in(!CollectionUtils.isEmpty(relationIds), MessageRelation::getId, relationIds)
            .in(!CollectionUtils.isEmpty(dto.getInnerTemplateIds()), MessageRelation::getTemplateId, dto.getInnerTemplateIds())
            .eq(MessageRelation::getIsDelete, TableIsDeleteEnum.NORMAL.value)
            .orderByDesc(MessageRelation::getCreateAt)
    );

  }

  @Override
  public MessageRelation getRelationById(Long id) {
    return messageRelationDao.getById(id);
  }

  @Override
  public List<MessageRelation> getRelationByIds(Set<Long> relationIds) {
    return messageRelationDao.listByIds(relationIds);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void delete(Long id) {
    MessageRelation mr = messageRelationDao.getById(id);
    MessageTemplate mt = templateService.getTemplateById(mr.getTemplateId());
    List<MessageRouter> routers = routerService.getRoutersByRelationId(mr.getId());
    messageRelationDao.removeById(id);
    templateService.removeById(mt);
    routerService.batchRemoveByIds(routers);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void syncData(List<SyncRelationDataDTO> dtos) {
    List<Long> changeRelationIds = dtos.stream().map(SyncRelationDataDTO::getId)
            .collect(Collectors.toList());
    List<Long> inDbRelationIds = messageRelationDao.listByIds(changeRelationIds).stream()
            .map(MessageRelation::getId).collect(
                    Collectors.toList());

    dtos.stream().filter(i -> inDbRelationIds.contains(i.getId())).forEach(i -> {
      // template
      MessageTemplate template = new MessageTemplate();
      template.setId(i.getTemplate().getId());
      template.setTitle(i.getTemplate().getTitle());
      template.setContent(i.getTemplate().getContent());
      templateService.saveOrUpdateTemplate(template);

      // relation
      MessageRelation relation = new MessageRelation();
      relation.setId(i.getId());
      relation.setModuleId(i.getModuleId());
      relation.setTypeId(0);
      relation.setTemplateId(i.getTemplateId());
      relation.setContactUser(i.getContactUser());
      messageRelationDao.updateById(relation);

      // router
      routerService.syncData(i);
    });

    dtos.stream().filter(i -> !inDbRelationIds.contains(i.getId())).forEach(i-> {

      templateService.insertNativeSql(i.getTemplate());

      messageRelationDao.insertSql(i);

      routerService.syncData(i);
    });

  }

  @Override
  public List<Long> listRelationIds(Collection<Long> moduleIds) {
    if (CollectionUtils.isEmpty(moduleIds)) {
      return Collections.emptyList();
    }
    return messageRelationDao.lambdaQuery()
            .in(MessageRelation::getModuleId, moduleIds)
            .eq(MessageRelation::getIsDelete, TableIsDeleteEnum.NORMAL.value)
            .select(MessageRelation::getId)
            .list().stream()
            .map(MessageRelation::getId)
            .collect(Collectors.toList());
  }

  @Override
  public void updateTemplateAudioFile(UpdateTemplateAudioFileReq param) {
    if (org.apache.commons.lang3.StringUtils.isBlank(param.getAudioFileName())) {
      return;
    }
    MessageRelation relation = messageRelationDao.getById(param.getRelationId());
    if (Objects.isNull(relation)) {
      return;
    }
    MessageTemplate template = templateService.getTemplateById(relation.getTemplateId());
    if (Objects.isNull(template)) {
      return;
    }
    MessageTemplate updateTemplate = new MessageTemplate();
    updateTemplate.setId(template.getId());
    updateTemplate.setAudioFileName(param.getAudioFileName());
    templateService.saveOrUpdateTemplate(updateTemplate);
  }
}
