package com.sunda.spmsuser.service.impl;

import com.sunda.spmscommon.ResponseResult;
import com.sunda.spmsuser.entity.SpmsMenu;
import com.sunda.spmsuser.entity.SpmsRoleMenu;
import com.sunda.spmsuser.mapper.SpmsMenuMapper;
import com.sunda.spmsuser.mapper.SpmsRoleMenuMapper;
import com.sunda.spmsuser.service.ISpmsMenuService;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * <p>
 * 菜单表 服务实现类
 * </p>
 *
 * @author Wayne
 * @since 2023-05-25
 */
@Service
public class SpmsMenuServiceImpl extends ServiceImpl<SpmsMenuMapper, SpmsMenu> implements ISpmsMenuService {
	
	@Autowired
	SpmsRoleMenuMapper spmsRoleMenuMapper;

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public IPage getMenuListByParam(JSONObject doc) {
		IPage page = new Page<>(doc.getInteger("pageNo"),doc.getInteger("pageSize"));
		SpmsMenu menu = new SpmsMenu();
		menu.setMenuName(doc.get("menuName") != null ? doc.getString("menuName") : null);
		menu.setMenuType(doc.get("menuType") != null && doc.get("menuType") != "" ? doc.getInteger("menuType") : null);
		List<Map<String, Object>> mapList = this.baseMapper.selectMenuListByPage(menu);
		List<Map<String, Object>> returnData = new ArrayList<Map<String, Object>>();
		if (CollectionUtils.isNotEmpty(mapList)) {
			List<Map<String, Object>> firstMap = new ArrayList<Map<String, Object>>();
			// 一级菜单
			List<Map<String, Object>> firstList = mapList.stream().filter(o -> "0".equals(o.get("menuType").toString())).collect(Collectors.toList());
			firstMap.addAll(firstList);
			// 二级菜单根据父ID分组
			Map<String, List<Map<String, Object>>> secondList = mapList.stream().filter(o -> o.get("parentId") != null).collect(Collectors.groupingBy(e -> e.get("parentId").toString()));
			if (secondList != null) {
				// 根据父ID查询一级菜单
				for (String parentId : secondList.keySet()) {
					SpmsMenu menu2 = new SpmsMenu();
					menu2.setMenuId(parentId);
					List<Map<String, Object>> first = this.baseMapper.selectMenuListByPage(menu2);
					firstMap.addAll(first);
				}
			}
			if (CollectionUtils.isNotEmpty(firstMap)) {
				// 一级菜单去重
				returnData = firstMap.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(m -> m.get("menuId").toString()))), ArrayList<Map<String, Object>>::new));
				if (secondList != null) {
					for (Map<String, Object> map : returnData) {
						List<Map<String, Object>> list = secondList.get(map.get("menuId").toString());
						map.put("children", list);
					}
				}
			}
		}
		page.setRecords(returnData);
        return page;
	}

	@Override
	public List<Map<String, Object>> getMenuList(JSONObject doc) {
		SpmsMenu menu = new SpmsMenu();
		menu.setMenuName(doc.getString("menuName"));
		menu.setParentId(doc.getString("parentId"));
		menu.setMenuType(doc.get("menuType") != null && doc.get("menuType") != "" ? doc.getInteger("menuType") : null);
		List<Map<String, Object>> mapList = this.baseMapper.selectMenuList(menu);
		return mapList;
	}

	@Override
	public ResponseResult createMenu(JSONObject doc, String userId) {
		if (!doc.containsKey("menuType") || doc.get("menuType") == null || !doc.containsKey("url") || !doc.containsKey("componentUrl") || !doc.containsKey("menuName")) {
			return ResponseResult.error("请求参数错误");
		}
		SpmsMenu spmsMenu = new SpmsMenu();
		spmsMenu.setParentId(doc.getString("parentId"));
		spmsMenu.setMenuName(doc.getString("menuName"));
		spmsMenu.setMenuEnName(doc.getString("menuEnName"));
		spmsMenu.setMenuFaName(doc.getString("menuFaName"));
		spmsMenu.setMenuRuName(doc.getString("menuRuName"));
		spmsMenu.setUrl(doc.getString("url"));
		spmsMenu.setComponentUrl(doc.getString("componentUrl"));
		spmsMenu.setComponentName(doc.getString("componentName"));
		spmsMenu.setMenuType(doc.getInteger("menuType"));
		spmsMenu.setSortNo(doc.getInteger("sortNo"));
		spmsMenu.setRedirect(doc.getString("redirect"));
		spmsMenu.setIcon(doc.getString("icon"));
		if (spmsMenu.getMenuType() == 1 && StringUtils.isBlank(spmsMenu.getParentId())) {
			return ResponseResult.error("二级菜单的ParentId不能为空");
		}
		// 未删除
		spmsMenu.setIsRoute(0);
		String menuId = doc.getString("menuId");
		if (StringUtils.isBlank(menuId)) {
			spmsMenu.setCreateTime(new Date());
			spmsMenu.setCreateUser(userId);
			synchronized (doc) {
				// 根据菜单级别查询当前级别最大的ID
				Map<String, Object> maxIdMap = this.baseMapper.selectMenuMaxId(spmsMenu);
				if (maxIdMap == null || maxIdMap.get("menuId") == null) {
					if (spmsMenu.getMenuType() == 0) {
						// 一级菜单
						menuId = "10";
					} else {
						// 二级菜单
						menuId = spmsMenu.getParentId()+"0010";
					}
				} else {
					String maxMenuId = maxIdMap.get("menuId").toString();
					Integer intId = Integer.valueOf(maxMenuId)+10;
					menuId = String.valueOf(intId);
				}
				spmsMenu.setMenuId(menuId);
				this.baseMapper.insert(spmsMenu);
				return ResponseResult.success();
			}
		} else {
			spmsMenu.setUpdateTime(new Date());
			spmsMenu.setUpdateUser(userId);
			this.baseMapper.update(spmsMenu, new QueryWrapper<SpmsMenu>().eq("MENU_ID", menuId));
			return ResponseResult.success();
		}
	}

	@Override
	@Transactional
	public ResponseResult deleteMenu(JSONObject doc, String userId) {
		if (!doc.containsKey("menuType") || doc.get("menuType") == null || doc.get("menuType") == "") {
			return ResponseResult.error("menuType请求参数错误");
		}
		if (!doc.containsKey("menuId") || doc.get("menuId") == null || doc.get("menuId") == "") {
			return ResponseResult.error("menuId请求参数错误");
		}
		SpmsMenu menu = new SpmsMenu();
		menu.setIsRoute(1);
		menu.setUpdateTime(new Date());
		menu.setUpdateUser(userId);
		this.baseMapper.update(menu, new QueryWrapper<SpmsMenu>().eq("MENU_ID", doc.getString("menuId")));
		// 如果是删除一级菜单，一级下的二级菜单也全部删除
		if (doc.getInteger("menuType") == 0) {
			// 删除一级菜单下的二级菜单
			this.baseMapper.update(menu, new QueryWrapper<SpmsMenu>().eq("PARENT_ID", doc.getString("menuId")));
		}
		// 删除角色、菜单关系表
		spmsRoleMenuMapper.delete(new QueryWrapper<SpmsRoleMenu>().eq("MENU_ID", doc.getString("menuId")));
		return ResponseResult.success();
	}

	@Override
	public List<Map<String, Object>> getMenuListByRoleId(JSONObject doc) {
		// 查询全部的菜单信息
		SpmsMenu spmsMenu = new SpmsMenu();
		List<Map<String, Object>> menuList = this.baseMapper.selectMenuList(spmsMenu);
		// 根据角色uuid查询角色菜单关系表这个角色分配了哪些菜单
		List<String> roleMenuList = this.baseMapper.selectRoleMenuList(doc.getString("roleUuid"));
		// 一级菜单分类
		List<Map<String, Object>> firstMenuList = menuList.stream().filter(map -> map.get("parentId") == null).collect(Collectors.toList());
		// 二级菜单分类-根据父级ID分组
		Map<String, List<Map<String, Object>>> secondMenuList = menuList.stream().filter(map -> map.get("parentId") != null).collect(Collectors.groupingBy(e -> e.get("parentId").toString()));
		// 组装树型结构
		for (Map<String, Object> map : firstMenuList) {
			// 存在只有一级的菜单
			if (CollectionUtils.isNotEmpty(roleMenuList) && roleMenuList.contains(map.get("menuId").toString())) {
				map.put("chooseType", "1");
			} else {
				map.put("chooseType", "0");
			}
			List<Map<String, Object>> list = secondMenuList.get(map.get("menuId").toString());
			// 如果二级菜单已分配这个角色，那么就打上标识
			if (CollectionUtils.isNotEmpty(list)) {
				for (Map<String, Object> secMap : list) {
					if (CollectionUtils.isNotEmpty(roleMenuList) && roleMenuList.contains(secMap.get("menuId").toString())) {
						secMap.put("chooseType", "1");
					} else {
						secMap.put("chooseType", "0");
					}
				}
			}
			map.put("children", list);
		}
		return firstMenuList;
	}

	@Override
	public List<Map<String, Object>> getMenuListByUserId(String userId) {
		// 根据用户ID查询用户分配的菜单
		List<Map<String, Object>> list = this.baseMapper.selectMenuListByUserId(userId);
		List<Map<String, Object>> returnList = new ArrayList<>();
		if (CollectionUtils.isNotEmpty(list)) {
			// 获取一级菜单ID
			Set<String> firstIDSet = list.stream().filter(m -> "0".equals(m.get("menuType").toString())).map(o -> o.get("menuId").toString()).collect(Collectors.toSet());
			// 查询一级菜单信息
			SpmsMenu spmsMenu = new SpmsMenu();
			spmsMenu.setMenuType(0);
			List<Map<String, Object>> firstMenuList = this.baseMapper.selectMenuList(spmsMenu);
			// 根据菜单ID分组
			Map<String, List<Map<String, Object>>> MenuIdMap = firstMenuList.stream().collect(Collectors.groupingBy(m -> m.get("menuId").toString()));
			// 获取一级菜单编码
			Set<String> firstMenuIds = list.stream().filter(o -> "1".equals(o.get("menuType").toString())).map(m -> m.get("parentId").toString()).collect(Collectors.toSet());
			firstIDSet.addAll(firstMenuIds);
			// 二级菜单分类-根据父级ID分组
			Map<String, List<Map<String, Object>>> secondMenuMaps = list.stream().filter(o -> "1".equals(o.get("menuType").toString())).collect(Collectors.groupingBy(e -> e.get("parentId").toString()));
			// 一级菜单排序
			Set<String> sortSet = new TreeSet<String>((o1, o2) -> Integer.valueOf(o1).compareTo(Integer.valueOf(o2)));
			sortSet.addAll(firstIDSet);
			for (String firstMenuId : sortSet) {
				List<Map<String, Object>> firstMenus = MenuIdMap.get(firstMenuId);
				Map<String, Object> map = firstMenus.get(0);
				List<Map<String, Object>> secondMenuList = secondMenuMaps.get(firstMenuId);
				map.put("childMenus", secondMenuList);
				returnList.add(map);
			}
		}
		return returnList;
	}

}
