package org.jeecg.modules.system.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.common.constant.FillRuleConstant;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.FillRuleUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.system.dto.ProductCategoryDTO;
import org.jeecg.modules.system.entity.SysCategory;
import org.jeecg.modules.system.mapper.SysCategoryMapper;
import org.jeecg.modules.system.model.TreeSelectModel;
import org.jeecg.modules.system.service.ISysCategoryService;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * @Description: 分类字典
 * @Author: jeecg-boot
 * @Date:   2019-05-29
 * @Version: V1.0
 */
@Service
public class SysCategoryServiceImpl extends ServiceImpl<SysCategoryMapper, SysCategory> implements ISysCategoryService {

	@Override
	public void addSysCategory(SysCategory sysCategory) {
		String categoryCode = "";
		String categoryPid = ISysCategoryService.ROOT_PID_VALUE;
		String parentCode = null;
		if(oConvertUtils.isNotEmpty(sysCategory.getPid())){
			categoryPid = sysCategory.getPid();

			//PID 不是根节点 说明需要设置父节点 hasChild 为1
			if(!ISysCategoryService.ROOT_PID_VALUE.equals(categoryPid)){
				SysCategory parent = baseMapper.selectById(categoryPid);
				parentCode = parent.getCode();
				if(parent!=null && !ISysCategoryService.HAS_CHILD.equals(parent.getHasChild())){
					parent.setHasChild(ISysCategoryService.HAS_CHILD);
					baseMapper.updateById(parent);
				}
			}
		}
		//update-begin--Author:baihailong  Date:20191209 for：分类字典编码规则生成器做成公用配置
		JSONObject formData = new JSONObject();
		formData.put("pid",categoryPid);
		categoryCode = (String) FillRuleUtil.executeRule(FillRuleConstant.CATEGORY,formData);
		//update-end--Author:baihailong  Date:20191209 for：分类字典编码规则生成器做成公用配置
		sysCategory.setCode(categoryCode);
		sysCategory.setPid(categoryPid);
		sysCategory.setParentCode(parentCode);
		baseMapper.insert(sysCategory);
	}

	@Override
	public void updateSysCategory(SysCategory sysCategory) {
		if(oConvertUtils.isEmpty(sysCategory.getPid())){
			sysCategory.setPid(ISysCategoryService.ROOT_PID_VALUE);
		}else{
			//如果当前节点父ID不为空 则设置父节点的hasChild 为1
			SysCategory parent = baseMapper.selectById(sysCategory.getPid());
			if(parent!=null && !ISysCategoryService.HAS_CHILD.equals(parent.getHasChild())){
				parent.setHasChild(ISysCategoryService.HAS_CHILD);
				baseMapper.updateById(parent);
			}
		}
		baseMapper.updateById(sysCategory);
	}

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

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

	@Override
	public List<TreeSelectModel> queryAllListByPid(String pid) {
		List<TreeSelectModel> ls = this.queryListByPid(pid);
		Integer level = 1;
		loadAllChild(ls, level);
		return ls;
	}

	private void loadAllChild(List<TreeSelectModel> ls, Integer level) {
		if (Objects.isNull(ls) || ls.isEmpty()) {
		} else {
			ls.forEach(child -> {
				child.setLevel(level);
				if (!child.isLeaf()) {
					List<TreeSelectModel> treeSelectModels = this.queryListByPid(child.getKey());
					child.setChildren(treeSelectModels);
					loadAllChild(treeSelectModels, level + 1);
				}
			});
		}

	}

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

	@Override
	public String queryIdByCode(String code) {
		return baseMapper.queryIdByCode(code);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void deleteSysCategory(String ids) {
		String allIds = this.queryTreeChildIds(ids, this.list());
		String pids = this.queryTreePids(ids);
		//1.删除时将节点下所有子节点一并删除
		this.baseMapper.deleteBatchIds(Arrays.asList(allIds.split(",")));
		//2.将父节点中已经没有下级的节点，修改为没有子节点
		if(oConvertUtils.isNotEmpty(pids)){
			LambdaUpdateWrapper<SysCategory> updateWrapper = new UpdateWrapper<SysCategory>()
					.lambda()
					.in(SysCategory::getId,Arrays.asList(pids.split(",")))
					.set(SysCategory::getHasChild,"0");
			this.update(updateWrapper);
		}
	}

	/**
	 * 查询节点下所有子节点
	 * @param ids
	 * @param categoryList
	 * @return
	 */
	@Override
	public String queryTreeChildIds(String ids, List<SysCategory> categoryList) {
		Map<String, List<SysCategory>> pidCategoryListMap = categoryList.stream()
				.collect(Collectors.groupingBy(SysCategory::getPid));
		//获取id数组
		String[] idArr = ids.split(",");
//		StringBuffer sb = new StringBuffer();
		ArrayList<String> idList = new ArrayList<>();
		for (String pidVal : idArr) {
			if(pidVal != null){
				if(!idList.contains(pidVal)){
//					if(!sb.toString().isEmpty()){
//						sb.append(",");
//					}
					idList.add(pidVal);
					this.getTreeChildIds(pidVal,idList, pidCategoryListMap);
				}
			}
		}
		return String.join(",", idList);
	}

	/**
	 * 根据名字查询某个分类下的所有分类
	 *
	 * @param categoryPId
	 * @param category
	 * @return
	 */
	@Override
	public List<SysCategory> listCategory(String categoryPId, String category) {

		if (StrUtil.isBlank(categoryPId)) {
			categoryPId = "0";
		}
		List<SysCategory> categoryList = this.list();
		List<String> subCategoryIds = Arrays.stream(queryTreeChildIds(categoryPId, categoryList).split(","))
				.collect(Collectors.toList());
        return categoryList.stream()
                .filter(c -> subCategoryIds.contains(c.getId()))
                .filter(c -> StrUtil.isBlank(category) || c.getName().contains(category))
                .collect(Collectors.toList());
	}

	/**
	 * 查询需修改标识的父节点ids
	 * @param ids
	 * @return
	 */
	private String queryTreePids(String ids) {
		StringBuffer sb = new StringBuffer();
		//获取id数组
		String[] idArr = ids.split(",");
		for (String id : idArr) {
			if(id != null){
				SysCategory category = this.baseMapper.selectById(id);
				//根据id查询pid值
				String metaPid = category.getPid();
				//查询此节点上一级是否还有其他子节点
				LambdaQueryWrapper<SysCategory> queryWrapper = new LambdaQueryWrapper<>();
				queryWrapper.eq(SysCategory::getPid,metaPid);
				queryWrapper.notIn(SysCategory::getId,Arrays.asList(idArr));
				List<SysCategory> dataList = this.baseMapper.selectList(queryWrapper);
                boolean flag = (dataList == null || dataList.size()==0) && !Arrays.asList(idArr).contains(metaPid)
                        && !sb.toString().contains(metaPid);
                if(flag){
					//如果当前节点原本有子节点 现在木有了，更新状态
					sb.append(metaPid).append(",");
				}
			}
		}
		if(sb.toString().endsWith(SymbolConstant.COMMA)){
			sb = sb.deleteCharAt(sb.length() - 1);
		}
		return sb.toString();
	}

	/**
	 * 递归 根据父id获取子节点id
	 *
	 * @param pidVal
	 * @param ids
	 * @param pidCategoryListMap
	 * @return
	 */
	private List<String> getTreeChildIds(String pidVal, List<String> ids, Map<String, List<SysCategory>> pidCategoryListMap){
//		LambdaQueryWrapper<SysCategory> queryWrapper = new LambdaQueryWrapper<>();
//		queryWrapper.eq(SysCategory::getPid,pidVal);
//		List<SysCategory> dataList = baseMapper.selectList(queryWrapper);
		List<SysCategory> dataList = pidCategoryListMap.get(pidVal);
		if(dataList != null && !dataList.isEmpty()){
			for(SysCategory category : dataList) {
				if(!ids.contains(category.getId())){
					ids.add(category.getId());
				}
				this.getTreeChildIds(category.getId(), ids, pidCategoryListMap);
			}
		}
		return ids;
	}

	@Override
	public List<String> loadDictItem(String ids) {
		return this.loadDictItem(ids, true);
	}

	@Override
	public List<String> loadDictItem(String ids, boolean delNotExist) {
		String[] idArray = ids.split(",");
		LambdaQueryWrapper<SysCategory> query = new LambdaQueryWrapper<>();
		query.in(SysCategory::getId, Arrays.asList(idArray));
		// 查询数据
		List<SysCategory> list = super.list(query);
		// 取出name并返回
		List<String> textList;
		// update-begin--author:sunjianlei--date:20210514--for：新增delNotExist参数，设为false不删除数据库里不存在的key ----
		if (delNotExist) {
			textList = list.stream().map(SysCategory::getName).collect(Collectors.toList());
		} else {
			textList = new ArrayList<>();
			for (String id : idArray) {
				List<SysCategory> res = list.stream().filter(i -> id.equals(i.getId())).collect(Collectors.toList());
				textList.add(res.size() > 0 ? res.get(0).getName() : id);
			}
		}
		// update-end--author:sunjianlei--date:20210514--for：新增delNotExist参数，设为false不删除数据库里不存在的key ----
		return textList;
	}

	@Override
	public List<String> loadDictItemByNames(String names, boolean delNotExist) {
		List<String> nameList = Arrays.asList(names.split(SymbolConstant.COMMA));
		LambdaQueryWrapper<SysCategory> query = new LambdaQueryWrapper<>();
		query.select(SysCategory::getId, SysCategory::getName);
		query.in(SysCategory::getName, nameList);
		// 查询数据
		List<SysCategory> list = super.list(query);
		// 取出id并返回
		return nameList.stream().map(name -> {
			SysCategory res = list.stream().filter(i -> name.equals(i.getName())).findFirst().orElse(null);
			if (res == null) {
				return delNotExist ? null : name;
			}
			return res.getId();
		}).filter(Objects::nonNull).collect(Collectors.toList());
	}

	@Override
	public Map<String, ProductCategoryDTO> getProductCategoryTextIdsMap() {

		HashMap<String, ProductCategoryDTO> categoryTextIdsMap = new HashMap<>();
		List<TreeSelectModel> models = getProductAllTreeCategory();

		HashMap<String, String> categoryIdTitleMap = getCategoryIdTitleMap(models);

		models.forEach(first -> {
			ProductCategoryDTO dtoFirst = ProductCategoryDTO.from(first.getKey());
			String firstTitle = categoryIdTitleMap.get(dtoFirst.getFirstCategory());
			categoryTextIdsMap.put(firstTitle, dtoFirst);
			if (!first.isLeaf()) {
				first.getChildren()
						.forEach(second -> {
							ProductCategoryDTO dtoSecond = ProductCategoryDTO.from(first.getKey(), second.getKey());
							String secondTitle = categoryIdTitleMap.get(dtoSecond.getSecondCategory());
							categoryTextIdsMap.put(firstTitle + "/" + secondTitle, dtoSecond);
							if (!second.isLeaf()) {
								second.getChildren()
										.forEach(third -> {
											ProductCategoryDTO dtoThird = ProductCategoryDTO.from(first.getKey(), second.getKey(), third.getKey());
											String thirdTitle = categoryIdTitleMap.get(dtoThird.getThirdCategory());
											categoryTextIdsMap.put(firstTitle + "/" + secondTitle + "/" + thirdTitle, dtoThird);
										});
							}
						});
			}
		});
		return categoryTextIdsMap;
	}

	@NotNull
	private HashMap<String, String> getCategoryIdTitleMap(List<TreeSelectModel> models) {
		HashMap<String, String> categoryIdTitleMap = new HashMap<>();
		models.forEach(first -> {
			categoryIdTitleMap.put(first.getKey(), first.getTitle());
			if (!first.isLeaf()) {
				first.getChildren()
						.forEach(second -> {
							categoryIdTitleMap.put(second.getKey(), second.getTitle());
							if (!second.isLeaf()) {
								second.getChildren()
										.forEach(third -> {
											categoryIdTitleMap.put(third.getKey(), third.getTitle());
										});
							}
						});
			}
		});
		return categoryIdTitleMap;
	}

	@Override
	public Map<String, ProductCategoryDTO> getProductCategoryIdIdsMap() {

		Map<String, ProductCategoryDTO> categoryIdIdsMap = new HashMap<>();
		List<TreeSelectModel> models = getProductAllTreeCategory();

		models.forEach(first -> {
			ProductCategoryDTO dtoFirst = ProductCategoryDTO.from(first.getKey());
			categoryIdIdsMap.put(first.getKey(), dtoFirst);
			if (!first.isLeaf()) {
				first.getChildren()
						.forEach(second -> {
							ProductCategoryDTO dtoSecond = ProductCategoryDTO.from(first.getKey(), second.getKey());
							categoryIdIdsMap.put(second.getKey(), dtoSecond);
							if (!second.isLeaf()) {
								second.getChildren()
										.forEach(third -> {
											ProductCategoryDTO dtoThird = ProductCategoryDTO.from(first.getKey(), second.getKey(), third.getKey());
											categoryIdIdsMap.put(third.getKey(), dtoThird);
										});
							}
						});
			}
		});

		return categoryIdIdsMap;
	}

	@Override
	public Map<String, String> getFirstAllCategoryMap() {

		Map<String, String> firstAllCategoryMap = new HashMap<>();
		List<TreeSelectModel> models = getProductAllTreeCategory();

		HashMap<String, String> categoryIdTitleMap = getCategoryIdTitleMap(models);

		models.forEach(first -> {
			String firstTitle = categoryIdTitleMap.get(first.getKey());
			firstAllCategoryMap.put(firstTitle, firstTitle);
			if (!first.isLeaf()) {
				first.getChildren()
						.forEach(second -> {
							String secondTitle = categoryIdTitleMap.get(second.getKey());
							firstAllCategoryMap.put(firstTitle, firstTitle + "/" + secondTitle);
							if (!second.isLeaf()) {
								second.getChildren()
										.forEach(third -> {
											String thirdTitle = categoryIdTitleMap.get(third.getKey());
											firstAllCategoryMap.put(firstTitle, firstTitle + "/" + secondTitle + "/" + thirdTitle);
										});
							}
						});
			}
		});
		return firstAllCategoryMap;
	}

	private List<TreeSelectModel> getProductAllTreeCategory() {
		return this.queryAllListByPid("1785139417047572481");
	}

	@Override
	public Map<String, String> getCategoryIdCodeMap() {
		Map<String, String> categoryIdCodeMap = new HashMap<>();
		getProductAllTreeCategory()
				.forEach(first -> {
					categoryIdCodeMap.put(first.getKey(), first.getCode());
					if (!first.isLeaf()) {
						first.getChildren()
								.forEach(second -> {
									categoryIdCodeMap.put(second.getKey(), second.getCode());
									if (!second.isLeaf()) {
										second.getChildren()
												.forEach(third -> {
													categoryIdCodeMap.put(third.getKey(), third.getCode());
												});
									}
								});
					}
				});
		return categoryIdCodeMap;
	}

	@Override
	public Map<String, String> getCategoryNameCodeMap() {
		Map<String, String> categoryNameCodeMap = new HashMap<>();
		getProductAllTreeCategory()
				.forEach(first -> {
					categoryNameCodeMap.put(first.getTitle(), first.getCode());
					if (!first.isLeaf()) {
						first.getChildren()
								.forEach(second -> {
									categoryNameCodeMap.put(second.getTitle(), second.getCode());
									if (!second.isLeaf()) {
										second.getChildren()
												.forEach(third -> {
													categoryNameCodeMap.put(third.getTitle(), third.getCode());
												});
									}
								});
					}
				});
		return categoryNameCodeMap;
	}
}
