/*
* Copyright (c) 京北方信息技术股份有限公司 Corporation 2022 . All rights reserved.
*
*/
package net.northking.cctp.scriptcase.api.comLib.service;

import net.northking.cctp.common.db.annotation.DatabaseWriteOnly;
import net.northking.cctp.common.exception.PlatformRuntimeException;
import net.northking.cctp.common.util.UUIDUtil;
import net.northking.cctp.scriptcase.api.component.service.AtuBusinessNoApiService;
import net.northking.cctp.scriptcase.constants.ScriptConstant;
import net.northking.cctp.scriptcase.db.entity.LibraryBusComInfo;
import net.northking.cctp.scriptcase.db.entity.LibraryBusComTree;
import net.northking.cctp.scriptcase.db.service.LibraryBusComInfoService;
import net.northking.cctp.scriptcase.db.service.LibraryBusComTreeService;
import net.northking.cctp.scriptcase.dto.comLib.LibraryBusComTreeAddDto;
import net.northking.cctp.scriptcase.dto.comLib.LibraryBusComTreeDetailDto;
import net.northking.cctp.scriptcase.dto.comLib.LibraryBusComTreeQueryDto;
import net.northking.cctp.scriptcase.dto.comLib.LibraryBusComTreeUpdateDto;
import net.northking.cctp.scriptcase.enums.ScriptCaseAppError;
import net.northking.cctp.scriptcase.tools.RuleDefinitionTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 业务组件库目录树服务实现类
 *
 * @author maven-cctp-plugin
 * @since 1.0
 */

@Service
@ConditionalOnMissingBean(name = "LibraryBusComTreeApiServiceImpl")
public class LibraryBusComTreeApiServiceImpl implements LibraryBusComTreeApiService
{
  /**
   * 日志
   */
  private final static Logger logger = LoggerFactory.getLogger(LibraryBusComTreeApiServiceImpl.class);

  @Autowired
  private LibraryBusComTreeService libraryBusComTreeService;
  @Autowired
  private LibraryBusComInfoService libraryBusComInfoService;
  @Autowired
  private AtuBusinessNoApiService atuBusinessNoApiService;

  @Override
  @DatabaseWriteOnly
  public String add(LibraryBusComTreeAddDto dto)
  {
    String splitStr = RuleDefinitionTool.getTreeSplit();
    //父目录下是否已经存在数据
    LibraryBusComInfo checkCom = new LibraryBusComInfo();
    checkCom.setIsDeleted(0);
    checkCom.setTreeId(dto.getParentId());
    if(!ScriptConstant.DATA_FIRST_NODE.equals(dto.getParentId()) && libraryBusComInfoService.count(checkCom)>0){
      //目录存在业务组件，不能增加子目录
      throw new PlatformRuntimeException(ScriptCaseAppError.TREE_ADD_EXISTS);
    }
    //同路径下目录校验
    LibraryBusComTree check = new LibraryBusComTree();
    check.setTreeName(dto.getTreeName());
    check.setParentId(dto.getParentId());
    check.setIsDeleted(0);
    if(libraryBusComTreeService.count(check)>0){
      //同级存在同名节点
      throw new PlatformRuntimeException(ScriptCaseAppError.TREE_NAME_EXISTS);
    }

    String uuid = UUIDUtil.create32UUID();
    LibraryBusComTree entity = new LibraryBusComTree();
    BeanUtils.copyProperties(dto, entity);
    entity.setId(uuid);
    entity.setIsLeaf(1);
    entity.setIsDeleted(0);

    //获取节点的排序值
    LibraryBusComTree idx = new LibraryBusComTree();
    idx.setParentId(dto.getParentId());

    if(ScriptConstant.DATA_FIRST_NODE.equals(entity.getParentId())){
      //顶层菜单添加
      entity.setIdPath(uuid);
      entity.setNamePath(ScriptConstant.DATA_FIRST_NODE+splitStr+dto.getTreeName());
      entity.setLevelNo(1);
    }else{
      LibraryBusComTree fa =this.libraryBusComTreeService.findByPrimaryKey(dto.getParentId());
      entity.setLevelNo(fa.getLevelNo()+1);
      entity.setIsLeaf(1);
      entity.setLevelNo(fa.getLevelNo()+1);
      entity.setNamePath(fa.getNamePath()+splitStr+entity.getTreeName());
      entity.setIdPath(fa.getIdPath()+splitStr+entity.getId());

      if(fa.getIsLeaf()==1){
        LibraryBusComTree up = new LibraryBusComTree();
        up.setId(fa.getId());
        up.setIsLeaf(0);//更改父节点为非叶子节点
        libraryBusComTreeService.updateByPrimaryKey(up);
      }
    }
    //获取排序值
    entity.setOrderSeq(atuBusinessNoApiService.genBusinessNo(null,ScriptConstant.LIB_BUS_COM_TREE,1L).get(0));
    this.libraryBusComTreeService.insert(entity);
    return uuid;
  }

  @Override
  @DatabaseWriteOnly
  public Integer updateByPK(LibraryBusComTreeUpdateDto dto) throws IllegalAccessException
  {
    String splitStr = RuleDefinitionTool.getTreeSplit();
    LibraryBusComTree old = libraryBusComTreeService.findByPrimaryKey(dto.getId());

    LibraryBusComTree check = new LibraryBusComTree();
    check.setTreeName(dto.getTreeName());
    check.setParentId(old.getParentId());
    check.setIsDeleted(0);
    List<LibraryBusComTree> checkList = libraryBusComTreeService.query(check);
    if(checkList.size()>0 && !checkList.get(0).getId().equals(dto.getId())){
      //同级存在同名节点
      throw new PlatformRuntimeException(ScriptCaseAppError.TREE_NAME_EXISTS);
    }
    LibraryBusComTree entity = new LibraryBusComTree();
    BeanUtils.copyProperties(dto, entity);

    //修改namePath
    LibraryBusComTree updateChild = new LibraryBusComTree();
    updateChild.setNamePath(old.getNamePath());

    String namePath = old.getNamePath();
    String namePathNew = ScriptConstant.DATA_FIRST_NODE;
    String[] nameArr = namePath.split(splitStr);
    for (int i = 1; i < nameArr.length-1; i++) {
      namePathNew = namePathNew +splitStr+ nameArr[i];
    }
    namePathNew = namePathNew+splitStr+dto.getTreeName();
    entity.setNamePath(null);
    int total = libraryBusComTreeService.updateByPrimaryKey(entity);
    //同步修改所有子级节点
    entity.setNamePath(namePathNew);
    total+= libraryBusComTreeService.updateChildNamePath(updateChild,namePathNew);

    return total;
  }

  @Override
  @DatabaseWriteOnly
  public Integer deleteByPK(String uuid)
  {
    LibraryBusComTree del = libraryBusComTreeService.findByPrimaryKey(uuid);
    if(del.getIsLeaf()==0){
      throw new PlatformRuntimeException(ScriptCaseAppError.TREE_NOT_LEAF_DELETE);
    }
    LibraryBusComInfo checkCount = new LibraryBusComInfo();
    checkCount.setTreeId(del.getId());
    checkCount.setIsDeleted(0);
    //校验节点下是否存在业务组件
    if(libraryBusComInfoService.queryCountByTreeCom(checkCount)>0){
      throw new PlatformRuntimeException(ScriptCaseAppError.TREE_COM_EXISTS);
    }
    LibraryBusComTree entity = new LibraryBusComTree();
    entity.setId(del.getId());
    entity.setIsDeleted(1);
    int num = libraryBusComTreeService.updateByPrimaryKey(entity);
    //查看上级节点是否无下级节点
    LibraryBusComTree count = new LibraryBusComTree();
    count.setIsDeleted(0);
    count.setParentId(del.getParentId());
    if(libraryBusComTreeService.count(count)<1){
      LibraryBusComTree up = new LibraryBusComTree();
      up.setId(del.getParentId());
      up.setIsLeaf(1);
      libraryBusComTreeService.updateByPrimaryKey(up);
    }
    return num;
  }

  @Override
  public List<LibraryBusComTreeDetailDto> findChildTreeList(LibraryBusComTreeQueryDto inputDto) {
    List<LibraryBusComTreeDetailDto> result = new ArrayList<>();
    //根据父节点查询所有子级节点
    LibraryBusComTree entity = new LibraryBusComTree();
    entity.setParentId(inputDto.getParentId());
    entity.setIsDeleted(0);
    result = libraryBusComTreeService.findChildTreeList(entity);
    return result;
  }

  @Override
  public List<LibraryBusComTreeDetailDto> findChildTreeListLike(LibraryBusComTreeQueryDto inputDto) {
    //模糊搜索所有节結點
    LibraryBusComTree queryAll = new LibraryBusComTree();
    queryAll.setIsDeleted(0);
    queryAll.setTreeName(inputDto.getTreeName());
    List<LibraryBusComTreeDetailDto> allList = libraryBusComTreeService.findChildTreeList(queryAll);
    if(allList.size()<1){
      return allList;
    }
    Map<String,LibraryBusComTreeDetailDto> toolMap = getToolMap(allList);
    List<LibraryBusComTreeDetailDto> dtoList = new ArrayList<>();
    for (String tool : toolMap.keySet()) {
      dtoList.add(toolMap.get(tool));
    }

    List<LibraryBusComTreeDetailDto> reList = genTreeList(dtoList);
    List<LibraryBusComTreeDetailDto> resList = reList.stream().sorted(Comparator.comparing(LibraryBusComTreeDetailDto::getOrderSeq)).collect(Collectors.toList());
    return resList;
  }


  private Map<String, LibraryBusComTreeDetailDto> getToolMap(List<LibraryBusComTreeDetailDto> allList) {
    Map<String, LibraryBusComTreeDetailDto> toolMap = new HashMap<>();
    List<Object> list = new ArrayList<>();
    for (int i = 0; i < allList.size(); i++) {
      LibraryBusComTreeDetailDto com = allList.get(i);
      String[] paths = com.getIdPath().split(RuleDefinitionTool.getTreeSplit());
      List<Object> ids = new ArrayList<>(Arrays.asList(paths));
      list.addAll(ids);
    }
    List<LibraryBusComTree> treeList = libraryBusComTreeService.findByPrimaryKeys(list);
    for (LibraryBusComTree tree : treeList) {
      LibraryBusComTreeDetailDto dto = new LibraryBusComTreeDetailDto();
      BeanUtils.copyProperties(tree, dto);
      if(!toolMap.containsKey(tree.getId())){
        toolMap.put(tree.getId(),dto);
      }
    }
    return toolMap;
  }

  private List<LibraryBusComTreeDetailDto> genTreeList(List<LibraryBusComTreeDetailDto> dtoList) {
    List<LibraryBusComTreeDetailDto> treeList = new ArrayList<>();
    for (int i = 0; i < dtoList.size(); i++) {
      LibraryBusComTreeDetailDto tree = dtoList.get(i);
      if(ScriptConstant.DATA_FIRST_NODE.equals(tree.getParentId())){
        getSonTree(tree,dtoList);
        treeList.add(tree);
      }
    }
    return treeList;
  }

  private void getSonTree(LibraryBusComTreeDetailDto tree, List<LibraryBusComTreeDetailDto> dtoList) {
    List<LibraryBusComTreeDetailDto> sonList = new ArrayList<>();
    for (LibraryBusComTreeDetailDto dto : dtoList) {
      if(tree.getId().equals(dto.getParentId())){
        getSonTree(dto,dtoList);
        sonList.add(dto);
      }
    }
    List<LibraryBusComTreeDetailDto> reSonList = sonList.stream().sorted(Comparator.comparing(LibraryBusComTreeDetailDto::getOrderSeq)).collect(Collectors.toList());
    tree.setChildren(reSonList);
  }
}
