package org.jeecg.modules.stm.base.domain.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.common.system.vo.SelectTreeModel;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;
import org.jeecg.modules.stm.base.domain.entity.StDomain;
import org.jeecg.modules.stm.base.domain.mapper.StDomainMapper;
import org.jeecg.modules.stm.base.domain.service.IStDomainService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.modules.stm.base.domain.vo.StDomainVo;
import org.jeecg.modules.stm.utils.StmConstans;
import org.jeecg.modules.stm.utils.UserUtil;

/**
 * @Description: st_domain
 * @Author: yzh
 * @Date:   2023-03-09
 * @Version: V1.0
 */
@Service
public class StDomainServiceImpl extends ServiceImpl<StDomainMapper, StDomain> implements IStDomainService {
    @Override
    public String getDomainCode(StDomain entity){
        // 上级编码为空
        if(StringUtils.isEmpty(entity.getUpperDomainCode())){
            QueryWrapper<StDomain> wapper = new QueryWrapper();
            wapper.eq("upper_domain_code",ROOT_PID_VALUE);
            wapper.orderByDesc("domain_code");
            wapper.last("limit 1");
            StDomain noUpperDomain = super.baseMapper.selectOne(wapper);
            // 如果为空，从001开始编码
            if(noUpperDomain == null) {
                return StringUtils.leftPad("1",2,"0");
            }else{
                // 如果不为空+1
                int no  = Integer.valueOf(noUpperDomain.getDomainCode())+1;
                if(no>99){
                    throw new JeecgBootException("一级领域编号已经超过100,无法在创建");
                }
                String str = ""+no;
                return StringUtils.leftPad(str,2,"0");
            }
        }else{
            // 上级编码不为空
            QueryWrapper<StDomain> wapper = new QueryWrapper();
            String upperCode = entity.getUpperDomainCode();
            wapper.eq("upper_domain_code",upperCode);
            wapper.orderByDesc("domain_code");
            wapper.last("limit 1");
            StDomain upperDomain = super.baseMapper.selectOne(wapper);
            // 如果为空，从1开始编码
            if(upperDomain == null) {
                return upperCode+StringUtils.leftPad("1",2,"0");
            }else{
                // 如果不为空+1
                int no  = Integer.valueOf(upperDomain.getDomainCode())+1;
                if(no%100==0){
                    throw new JeecgBootException("二级领域编号已经超过100,无法在创建");
                }
                String str = ""+no;
                return StringUtils.leftPad(str,2*(entity.getLevel()),"0");
            }
        }
    }


    private void checkName(StDomain entity, boolean isSave){
        if(entity==null){
            return;
        }
        QueryWrapper<StDomain> wapper = new QueryWrapper<>();
        wapper.eq("DOMAIN_NAME",entity.getDomainName());
        if(!isSave){
            //wapper.ne("DOMAIN_CODE",entity.getDomainCode());
            wapper.ne("id",entity.getId());
        }
        long count = super.count(wapper);
        if(count>0){
            throw new JeecgBootException("领域名称已存在");
        }
    }
	@Override
	public void addStDomain(StDomain stDomain) {
        checkName(stDomain,true);
        if(oConvertUtils.isEmpty(stDomain.getDomainCode())){
            String domainCode = getDomainCode(stDomain);
            stDomain.setDomainCode(domainCode);
        }
        stDomain.setCreatedUser(UserUtil.getUserCode());
        stDomain.setValid(StmConstans.DEFAULT_VALID);
        stDomain.setApproveFlag(StmConstans.DEFAULT_APPROVE_Flag);
	   //新增时设置hasChild为0
	    stDomain.setHasChild(IStDomainService.NOCHILD);
		if(oConvertUtils.isEmpty(stDomain.getUpperDomainCode())){
			stDomain.setUpperDomainCode(IStDomainService.ROOT_PID_VALUE);
		}else{
			//如果当前节点父ID不为空 则设置父节点的hasChildren 为1
            QueryWrapper<StDomain> wapper = new QueryWrapper();
            wapper.eq("domain_code", stDomain.getUpperDomainCode());
            wapper.last("limit 1");
			StDomain parent = baseMapper.selectOne(wapper);
			if(parent!=null && !"1".equals(parent.getHasChild())){
				parent.setHasChild("1");
				baseMapper.updateById(parent);
			}
		}
		baseMapper.insert(stDomain);
	}
	
	@Override
	public void updateStDomain(StDomain stDomain) {
        checkName(stDomain,false);
		StDomain entity = this.getById(stDomain.getId());
		if(entity==null) {
			throw new JeecgBootException("未找到对应实体");
		}
		String old_pid = entity.getUpperDomainCode();
		String new_pid = stDomain.getUpperDomainCode();
		if(!old_pid.equals(new_pid)) {
			updateOldParentNode(old_pid);
			if(oConvertUtils.isEmpty(new_pid)){
				stDomain.setUpperDomainCode(IStDomainService.ROOT_PID_VALUE);
			}
			if(!IStDomainService.ROOT_PID_VALUE.equals(stDomain.getUpperDomainCode())) {
				baseMapper.updateTreeNodeStatus(stDomain.getUpperDomainCode(), IStDomainService.HASCHILD);
			}
		}
        // 设置更新人员
        stDomain.setUpdatedUser(UserUtil.getUserCode());
		baseMapper.updateById(stDomain);
	}
	
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void deleteStDomain(String id) throws JeecgBootException {
		//查询选中节点下所有子节点一并删除
        id = this.queryTreeChildIds(id);
        if(id.indexOf(",")>0) {
            StringBuffer sb = new StringBuffer();
            String[] idArr = id.split(",");
            for (String idVal : idArr) {
                if(idVal != null){
                    StDomain stDomain = this.getById(idVal);
                    String pidVal = stDomain.getUpperDomainCode();
                    //查询此节点上一级是否还有其他子节点
                    List<StDomain> dataList = baseMapper.selectList(new QueryWrapper<StDomain>().eq("upper_domain_code", pidVal).notIn("id",Arrays.asList(idArr)));
                    boolean flag = (dataList == null || dataList.size() == 0) && !Arrays.asList(idArr).contains(pidVal) && !sb.toString().contains(pidVal);
                    if(flag){
                        //如果当前节点原本有子节点 现在木有了，更新状态
                        sb.append(pidVal).append(",");
                    }
                }
            }
            //批量删除节点
            baseMapper.deleteBatchIds(Arrays.asList(idArr));
            //修改已无子节点的标识
            String[] pidArr = sb.toString().split(",");
            for(String pid : pidArr){
                this.updateOldParentNode(pid);
            }
        }else{
            StDomain stDomain = this.getById(id);
            if(stDomain==null) {
                throw new JeecgBootException("未找到对应实体");
            }
            updateOldParentNode(stDomain.getUpperDomainCode());
            baseMapper.deleteById(id);
        }
	}
	
	@Override
    public List<StDomain> queryTreeListNoPage(QueryWrapper<StDomain> queryWrapper) {
        List<StDomain> dataList = baseMapper.selectList(queryWrapper);
        List<StDomain> mapList = new ArrayList<>();
        for(StDomain data : dataList){
            String pidVal = data.getUpperDomainCode();
            //递归查询子节点的根节点
            if(pidVal != null && !IStDomainService.NOCHILD.equals(pidVal)){
                StDomain rootVal = this.getTreeRoot(pidVal);
                if(rootVal != null && !mapList.contains(rootVal)){
                    mapList.add(rootVal);
                }
            }else{
                if(!mapList.contains(data)){
                    mapList.add(data);
                }
            }
        }
        return mapList;
    }

    @Override
    public List<SelectTreeModel> queryListByCode(String parentCode) {
        String pid = ROOT_PID_VALUE;
        if (oConvertUtils.isNotEmpty(parentCode)) {
            LambdaQueryWrapper<StDomain> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(StDomain::getUpperDomainCode, parentCode);
            List<StDomain> list = baseMapper.selectList(queryWrapper);
            if (list == null || list.size() == 0) {
                throw new JeecgBootException("该编码【" + parentCode + "】不存在，请核实!");
            }
            if (list.size() > 1) {
                throw new JeecgBootException("该编码【" + parentCode + "】存在多个，请核实!");
            }
            pid = list.get(0).getDomainCode();
        }
        return baseMapper.queryListByPid(pid, null);
    }

    @Override
    public List<SelectTreeModel> queryListByPid(String pid) {
        if (oConvertUtils.isEmpty(pid)) {
            pid = ROOT_PID_VALUE;
        }
        return baseMapper.queryListByPid(pid, null);
    }

    @Override
    public StDomainVo queryEntityByCode(String domainCode) {
        QueryWrapper<StDomain> wapper = new QueryWrapper();
        wapper.eq("domain_code",domainCode);
        wapper.last("limit 1");
        StDomain domain = super.baseMapper.selectOne(wapper);
        if(domain==null){
            return null;
        }
        StDomainVo stDomainVo = new StDomainVo();
        BeanUtils.copyProperties(domain,stDomainVo);
        if(ROOT_PID_VALUE.equals(domain.getUpperDomainCode())){
            stDomainVo.setPathDomainName(stDomainVo.getDomainName());
            stDomainVo.setFirstDomainName(stDomainVo.getDomainName());
        }else{
            StDomainVo stDomain = queryEntityByCode(stDomainVo.getUpperDomainCode());
            if(ROOT_PID_VALUE.equals(stDomain.getUpperDomainCode())){
                stDomainVo.setFirstDomainName(stDomain.getDomainName());
            }
            if(stDomain!=null && StringUtils.isNotEmpty(stDomain.getDomainCode())){
                // 父级+本级
                String pathDomain = stDomain.getPathDomainName()+"/"+stDomainVo.getDomainName();
                stDomainVo.setPathDomainName(pathDomain);
            }else{
                String pathDomain = "-"+"/"+stDomainVo.getDomainName();
                stDomainVo.setPathDomainName(pathDomain);
            }
        }
        return stDomainVo;
    }

    @Override
    public void changeParent(StDomain stDomain) {
        Integer id = stDomain.getId();
        StDomain stDomain1 = getById(id);
        // 如果 父级编码没有变更就返回
        if(stDomain1.getUpperDomainCode().equals(stDomain.getUpperDomainCode())){
            return;
        }
        if(stDomain.getDomainCode().equals(stDomain.getUpperDomainCode())){
            throw new JeecgBootException("不能选择自己做为父级节点！");
        }
        String domainCode = stDomain.getDomainCode();
        Integer level = stDomain.getLevel();
        // 计算是否还有其他子级
        QueryWrapper<StDomain> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("UPPER_DOMAIN_CODE",stDomain1.getUpperDomainCode());
        queryWrapper1.ne("DOMAIN_CODE",domainCode);
        long count = count(queryWrapper1);
        // 没有其他子节点变更是无子节点状态
        if(count==0){
            UpdateWrapper updateWrapper = new UpdateWrapper<>();
            updateWrapper.set("HAS_CHILD","0");
            updateWrapper.eq("DOMAIN_CODE",stDomain1.getUpperDomainCode());
            update(updateWrapper);
        }
        // 查看变更的父节点是否有子节点
        QueryWrapper<StDomain> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.eq("UPPER_DOMAIN_CODE",stDomain.getUpperDomainCode());
        long count2 = count(queryWrapper2);
        if(count2 == 0){
            UpdateWrapper updateWrapper = new UpdateWrapper<>();
            updateWrapper.set("HAS_CHILD","1");
            updateWrapper.eq("DOMAIN_CODE",stDomain.getUpperDomainCode());
            update(updateWrapper);
        }
        // 计算等级变更
        QueryWrapper<StDomain> queryWrapperLevel = new QueryWrapper<>();
        queryWrapperLevel.eq("DOMAIN_CODE",stDomain.getUpperDomainCode());
        queryWrapperLevel.last("limit 1");
        StDomain stDomainLevel = getOne(queryWrapperLevel);
        stDomain.setLevel(stDomainLevel.getLevel()+1);
        String domainCodes = getDomainCode(stDomain);
        // 变更父节点和节点代码
        UpdateWrapper updateChangeWrapper = new UpdateWrapper<>();
        updateChangeWrapper.set("DOMAIN_CODE",domainCodes);
        updateChangeWrapper.set("LEVEL",stDomain.getLevel());
        updateChangeWrapper.set("UPPER_DOMAIN_CODE",stDomain.getUpperDomainCode());
        updateChangeWrapper.eq("id",stDomain.getId());
        update(updateChangeWrapper);

        if(level==2) {
            // 查询子级数据
            QueryWrapper<StDomain> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("UPPER_DOMAIN_CODE", domainCode);
            List<StDomain> stList = list(queryWrapper);
            if(!CollectionUtils.isEmpty(stList)){
               for(StDomain stDomain2:stList){
                   String newCodes = stDomain2.getDomainCode();
                   newCodes = newCodes.replace(stDomain2.getUpperDomainCode(),domainCodes);
                   UpdateWrapper updateWrapper = new UpdateWrapper<>();
                   updateWrapper.set("DOMAIN_CODE",newCodes);
                   updateWrapper.set("UPPER_DOMAIN_CODE",domainCodes);
                   updateWrapper.eq("id",stDomain2.getId());
                   update(updateWrapper);
               }
            }
        }
    }

    /**
	 * 根据所传pid查询旧的父级节点的子节点并修改相应状态值
	 * @param pid
	 */
	private void updateOldParentNode(String pid) {
		if(!IStDomainService.ROOT_PID_VALUE.equals(pid)) {
			Long count = baseMapper.selectCount(new QueryWrapper<StDomain>().eq("upper_domain_code", pid));
			if(count==null || count<=1) {
				baseMapper.updateTreeNodeStatus(pid, IStDomainService.NOCHILD);
			}
		}
	}

	/**
     * 递归查询节点的根节点
     * @param pidVal
     * @return
     */
    private StDomain getTreeRoot(String pidVal){
        StDomain data =  baseMapper.selectById(pidVal);
        if(data != null && !IStDomainService.ROOT_PID_VALUE.equals(data.getUpperDomainCode())){
            return this.getTreeRoot(data.getUpperDomainCode());
        }else{
            return data;
        }
    }

    /**
     * 根据id查询所有子节点id
     * @param ids
     * @return
     */
    private String queryTreeChildIds(String ids) {
        //获取id数组
        String[] idArr = ids.split(",");
        StringBuffer sb = new StringBuffer();
        for (String pidVal : idArr) {
            if(pidVal != null){
                if(!sb.toString().contains(pidVal)){
                    if(sb.toString().length() > 0){
                        sb.append(",");
                    }
                    sb.append(pidVal);
                    this.getTreeChildIds(Integer.valueOf(pidVal),sb);
                }
            }
        }
        return sb.toString();
    }

    private String id2domainCode(Integer id){
        if(id == null){
            return null;
        }
        StDomain stDomain= baseMapper.selectById(id);
        if(stDomain == null){
            return null;
        }
        return stDomain.getDomainCode();
    }
    /**
     * 递归查询所有子节点
     * @param pidVal
     * @param sb
     * @return
     */
    private StringBuffer getTreeChildIds(Integer pidVal,StringBuffer sb){
        String upCode = id2domainCode(pidVal);
        if(StringUtils.isEmpty(upCode)){
            return sb;
        }
        List<StDomain> dataList = baseMapper.selectList(new QueryWrapper<StDomain>().eq("upper_domain_code", upCode));
        if(dataList != null && dataList.size()>0){
            for(StDomain tree : dataList) {
                if(!sb.toString().contains(tree.getDomainCode())){
                    sb.append(",").append(tree.getId());
                }
                this.getTreeChildIds(tree.getId(),sb);
            }
        }
        return sb;
    }

    @Override
    public  Map<String,String> getAllParentCode(List<String> codes) {
        List<String> codeList = new ArrayList<>();
        for(int i=0;i<codes.size();i++) {
            String strCode = codes.get(i);
            if(strCode==null) continue;
            for (int j = 2; j <= strCode.length(); j = j + 2) {
                String tmpCode = codes.get(i).substring(0, j);
                if(!codeList.contains(tmpCode)) {
                    codeList.add(tmpCode);
                }
            }
        }
        QueryWrapper<StDomain> queryWrapper = new QueryWrapper<>();
        if(codeList.size()>0) {
            queryWrapper.in("domain_code", codeList).orderByAsc("domain_code");
        }
        List<StDomain>  retList = baseMapper.selectList(queryWrapper);
        Map<String,String> codeNameMap = new HashMap<>();
        for (int i = 0; i < retList.size();i++) {
            StDomain stDomain = retList.get(i);
            codeNameMap.put(stDomain.getDomainCode(),stDomain.getDomainName());
        }
        Map<String,String> retMap = new HashMap<>();
        for(int i=0;i<codes.size();i++) {
            String strCode = codes.get(i);
            if(strCode==null) continue;
            StringBuffer sb = new StringBuffer();
            for (int j = 2; j <= strCode.length(); j = j + 2) {
                String tmpCode = codes.get(i).substring(0, j);
                sb.append("/").append(codeNameMap.get(tmpCode));
            }
            if(sb.length()>0){
                retMap.put(codes.get(i), sb.substring(1));
            } else {
                retMap.put(codes.get(i), "");
            }

        }
        return retMap;
    }

}
