package com.yunzhupaas.base.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yunzhupaas.base.Page;
import com.yunzhupaas.base.Pagination;
import com.yunzhupaas.base.UserInfo;
import com.yunzhupaas.base.entity.ModuleDataEntity;
import com.yunzhupaas.base.entity.SystemEntity;
import com.yunzhupaas.base.mapper.ModuleDataMapper;
import com.yunzhupaas.base.model.module.ModuleModel;
import com.yunzhupaas.base.service.ModuleDataService;
import com.yunzhupaas.base.service.ModuleService;
import com.yunzhupaas.base.service.SuperServiceImpl;
import com.yunzhupaas.base.service.SystemService;
import com.yunzhupaas.config.ConfigValueUtil;
import com.yunzhupaas.constant.YunzhupaasConst;
import com.yunzhupaas.consts.DeviceType;
import com.yunzhupaas.database.util.TenantDataSourceUtil;
import com.yunzhupaas.model.UserMenuModel;
import com.yunzhupaas.model.login.AllMenuSelectVO;
import com.yunzhupaas.model.tenant.TenantAuthorizeModel;
import com.yunzhupaas.permission.model.authorize.AuthorizeVO;
import com.yunzhupaas.permission.service.AuthorizeService;
import com.yunzhupaas.util.JsonUtil;
import com.yunzhupaas.util.RandomUtil;
import com.yunzhupaas.util.StringUtil;
import com.yunzhupaas.util.UserProvider;
import com.yunzhupaas.util.treeutil.ListToTreeUtil;
import com.yunzhupaas.util.treeutil.SumTree;
import com.yunzhupaas.util.treeutil.newtreeutil.TreeDotUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 *
 *
 * @author 云筑产品开发平台组
 * @version V3.4.2
 * @copyright 深圳市乐程软件有限公司（http://www.szlecheng.cn）
 * @date 2022/5/30
 */
@Service
public class ModuleDataServiceImpl extends SuperServiceImpl<ModuleDataMapper, ModuleDataEntity>
		implements ModuleDataService {

	@Autowired
	private ModuleService moduleService;
	@Autowired
	private SystemService systemService;
	@Autowired
	private AuthorizeService authorizeApi;
	@Autowired
	private ConfigValueUtil configValueUtil;

	@Override
	public List<ModuleDataEntity> getList(String category, Page page) {
		List<ModuleModel> moduleModels = menuList(category).stream().filter(t -> category.equals(t.getCategory()))
				.collect(Collectors.toList());
		if (StringUtil.isNotEmpty(page.getKeyword())) {
			moduleModels = moduleModels.stream().filter(t -> t.getFullName().contains(page.getKeyword()))
					.collect(Collectors.toList());
		}
		List<String> moduleId = moduleModels.stream().map(ModuleModel::getId).collect(Collectors.toList());
		if (moduleId.size() == 0) {
			return new ArrayList<>();
		}
		UserInfo userInfo = UserProvider.getUser();
		QueryWrapper<ModuleDataEntity> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda().eq(ModuleDataEntity::getCreatorUserId, userInfo.getUserId());
		queryWrapper.lambda().eq(ModuleDataEntity::getModuleType, category);
		queryWrapper.lambda().in(ModuleDataEntity::getModuleId, moduleId);
		return this.list(queryWrapper);
	}

	@Override
	public void create(String moduleId) {
		UserInfo userInfo = UserProvider.getUser();
		boolean pc = DeviceType.PC.getDevice().equals(userInfo.getLoginDevice());
		ModuleDataEntity entity = new ModuleDataEntity();
		entity.setId(RandomUtil.uuId());
		entity.setCreatorUserId(userInfo.getUserId());
		entity.setCreatorTime(new Date());
		entity.setEnabledMark(1);
		entity.setModuleId(moduleId);
		entity.setSystemId(pc ? userInfo.getSystemId() : userInfo.getAppSystemId());
		entity.setModuleType(pc ? "Web" : "App");
		this.save(entity);
	}

	@Override
	public ModuleDataEntity getInfo(String ObjectId) {
		UserInfo userInfo = UserProvider.getUser();
		boolean pc = DeviceType.PC.getDevice().equals(userInfo.getLoginDevice());
		QueryWrapper<ModuleDataEntity> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda().eq(ModuleDataEntity::getModuleId, ObjectId).eq(ModuleDataEntity::getCreatorUserId,
				userInfo.getUserId());
		queryWrapper.lambda().eq(ModuleDataEntity::getModuleType, pc ? "Web" : "App");
		return this.getOne(queryWrapper);
	}

	@Override
	public boolean isExistByObjectId(String moduleId) {
		UserInfo userInfo = UserProvider.getUser();
		boolean pc = DeviceType.PC.getDevice().equals(userInfo.getLoginDevice());
		QueryWrapper<ModuleDataEntity> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda().eq(ModuleDataEntity::getModuleId, moduleId)
				.eq(ModuleDataEntity::getModuleType, pc ? "Web" : "App")
				.eq(ModuleDataEntity::getCreatorUserId, userInfo.getUserId());
		return this.count(queryWrapper) > 0 ? true : false;
	}

	@Override
	public void delete(ModuleDataEntity entity) {
		this.removeById(entity.getId());
	}

	@Override
	public void delete(String moduleId) {
		QueryWrapper<ModuleDataEntity> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda().eq(ModuleDataEntity::getModuleId, moduleId);
		this.remove(queryWrapper);
	}

	@Override
	public List<AllMenuSelectVO> getDataList(Page page) {
		List<String> idAll = getList("App", new Page()).stream().map(ModuleDataEntity::getModuleId)
				.collect(Collectors.toList());
		List<ModuleModel> menuListAll = menuList();
		List<ModuleModel> menuList = menuListAll;
		if (StringUtil.isNotEmpty(page.getKeyword())) {
			menuList = menuList.stream().filter(t -> t.getFullName().contains(page.getKeyword()))
					.collect(Collectors.toList());
		}
		List<UserMenuModel> list = JsonUtil.getJsonToList(ListToTreeUtil.treeWhere(menuList, menuListAll),
				UserMenuModel.class);
		for (UserMenuModel model : list) {
			model.setIsData(idAll.contains(model.getId()));
		}
		List<UserMenuModel> modelList = modelList(list);
		List<SumTree<UserMenuModel>> menuAll = TreeDotUtils.convertListToTreeDot(modelList, "-1");
		List<AllMenuSelectVO> data = JsonUtil.getJsonToList(menuAll, AllMenuSelectVO.class);
		return data;
	}

	@Override
	public List<AllMenuSelectVO> getAppDataList(Pagination pagination) {
		List<AllMenuSelectVO> listVO = new LinkedList<>();
		List<String> idAll = getList("App", new Page()).stream().map(ModuleDataEntity::getModuleId)
				.collect(Collectors.toList());
		List<ModuleModel> moduleModels = menuList();
		List<ModuleModel> appData = moduleModels.stream().filter(t -> idAll.contains(t.getId()))
				.collect(Collectors.toList());
		String keyword = pagination.getKeyword();
		if (StringUtil.isNotEmpty(keyword)) {
			appData = appData.stream().filter(t -> t.getFullName().contains(keyword)).collect(Collectors.toList());
		}
		if (appData.size() == 0) {
			return new ArrayList<>();
		}
		List<UserMenuModel> list = JsonUtil.getJsonToList(ListToTreeUtil.treeWhere(appData, moduleModels),
				UserMenuModel.class);
		List<UserMenuModel> modelList = modelList(list);
		List<SumTree<UserMenuModel>> menuAll = TreeDotUtils.convertListToTreeDot(modelList);
		listVO.addAll(JsonUtil.getJsonToList(menuAll, AllMenuSelectVO.class));
		return listVO;
	}

	private List<UserMenuModel> modelList(List<UserMenuModel> list) {
		List<UserMenuModel> lists = list.stream().filter(t -> "-1".equals(t.getParentId()))
				.collect(Collectors.toList());
		List<UserMenuModel> modelList = new ArrayList<>();
		for (UserMenuModel userMenuModel : lists) {
			List<String> idList = new ArrayList<>();
			String id = userMenuModel.getId();
			parentList(list, id, idList);
			List<UserMenuModel> collect = list.stream().filter(t -> idList.contains(t.getId()))
					.collect(Collectors.toList());
			for (UserMenuModel menuModel : collect) {
				menuModel.setParentId(id);
			}
			modelList.addAll(collect);
			modelList.add(userMenuModel);
		}
		return modelList;
	}

	private void parentList(List<UserMenuModel> list, String parentId, List<String> idList) {
		List<UserMenuModel> menuList = list.stream().filter(t -> parentId.equals(t.getParentId()))
				.collect(Collectors.toList());
		for (UserMenuModel menu : menuList) {
			List<UserMenuModel> collect = list.stream().filter(t -> t.getParentId().equals(menu.getId()))
					.collect(Collectors.toList());
			idList.addAll(collect.stream().filter(t -> !Objects.equals(t.getType(), 1)).map(UserMenuModel::getId)
					.collect(Collectors.toList()));
			if (collect.size() > 0) {
				parentList(list, menu.getId(), idList);
			}
			if (!Objects.equals(menu.getType(), 1)) {
				idList.add(menu.getId());
			}
		}
	}

	private List<ModuleModel> menuList() {
		String appSystemId = UserProvider.getUser().getAppSystemId();
		AuthorizeVO authorizeModel = authorizeApi.getAuthorizeByUser(false);
		List<ModuleModel> menuList = authorizeModel.getModuleList().stream()
				.filter(t -> "App".equals(t.getCategory()) && t.getSystemId().equals(appSystemId))
				.collect(Collectors.toList());
		return menuList;
	}

	private List<ModuleModel> menuList(String category) {
		String systemId = "Web".equals(category) ? UserProvider.getUser().getSystemId()
				: UserProvider.getUser().getAppSystemId();
		AuthorizeVO authorizeModel = authorizeApi.getAuthorizeByUser(true);
		boolean enabledFow = true;
		// 获取应用
		if (configValueUtil.isMultiTenancy()) {
			TenantAuthorizeModel tenantAuthorizeModel = TenantDataSourceUtil
					.getCacheModuleAuthorize(UserProvider.getUser().getTenantId());
			List<String> cacheModuleAuthorize = tenantAuthorizeModel.getModuleIdList();
			if (cacheModuleAuthorize != null) {
				enabledFow = !cacheModuleAuthorize.contains("-999");
			}
		}
		SystemEntity info = systemService.getInfo(systemId);
		List<ModuleModel> menuList = authorizeModel.getModuleList().stream()
				.filter(t -> category.equals(t.getCategory()) && t.getSystemId().equals(systemId))
				.collect(Collectors.toList());
		if (info != null && enabledFow && Objects.equals(info.getWorkflowEnabled(), 1)) {
			menuList.addAll(JsonUtil.getJsonToList(moduleService.getListByEnCode(YunzhupaasConst.MODULE_CODE),
					ModuleModel.class));
		}
		return menuList;
	}

}
