package com.hotent.portal.persistence.manager.impl;

import java.io.File;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.hotent.base.util.*;
import com.hotent.base.util.Base64;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hotent.base.conf.SaaSConfig;
import com.hotent.base.exception.BaseException;
import com.hotent.base.manager.impl.BaseManagerImpl;
import com.hotent.base.model.CommonResult;
import com.hotent.portal.model.PortalNewsNotice;
import com.hotent.portal.model.PortalNewsTree;
import com.hotent.portal.model.SysIndexColumn;
import com.hotent.portal.model.SysIndexNewsColumn;
import com.hotent.portal.persistence.dao.PortalNewsTreeDao;
import com.hotent.portal.persistence.manager.PortalNewsNoticeManager;
import com.hotent.portal.persistence.manager.PortalNewsTreeManager;
import com.hotent.portal.persistence.manager.SysIndexColumnManager;
import com.hotent.portal.persistence.manager.SysIndexNewsColumnManager;
import com.hotent.sys.persistence.manager.SysAuthUserManager;
import com.hotent.uc.api.impl.util.ContextUtil;
import com.hotent.uc.api.model.IUser;

/**
 *  服务实现类
 *
 * @company 广州宏天软件股份有限公司
 * @author 赵祥云
 * @since 2020-07-03
 */
@Service
public class PortalNewsTreeManagerImpl extends BaseManagerImpl<PortalNewsTreeDao, PortalNewsTree> implements PortalNewsTreeManager {

	@Autowired
	SysIndexColumnManager sysIndexColumnManager;

	@Resource
	SysIndexNewsColumnManager sysIndexNewsColumnManager;

	@Resource
	PortalNewsNoticeManager portalNewsNoticeManager;

	@Resource
	PortalNewsTreeDao portalNewsTreeDao;

	@Resource
	SysAuthUserManager sysAuthUserManager;

	@Resource
	SaaSConfig saaSConfig;

	@Override
	public CommonResult<String> issue(String id) throws Exception {
		SysIndexColumn sysIndexColumn=new SysIndexColumn();
		PortalNewsTree portalNewsTree = this.get(id);
		//判断这个分类是不是已经发布了分类,并且这个分类没被删除
		String columnId = portalNewsTree.getColumnId();
		if(StringUtil.isNotEmpty(columnId)){
			SysIndexColumn sysIndexColumn2 = sysIndexColumnManager.get(columnId);
			if(BeanUtils.isNotEmpty(sysIndexColumn2)){
				return new CommonResult<String>(false,"此分类已经被发布成首页栏目,无法再次发布!");
			}
		}
		String path = portalNewsTree.getPath();
		sysIndexColumn.setAlias(id);
		sysIndexColumn.setCatalog("31081");
		sysIndexColumn.setColHeight(327L);
		sysIndexColumn.setColType((short)0);
		sysIndexColumn.setIsPublic((short)2);
		sysIndexColumn.setNeedPage((short)0);
		sysIndexColumn.setCatalogName("默认分类");
		sysIndexColumn.setColHeight(BeanUtils.isNotEmpty(portalNewsTree.getColHeight())?portalNewsTree.getColHeight().longValue():Long.valueOf(100));
		String suid = UniqueIdUtil.getSuid();
		sysIndexColumn.setId(suid);
		sysIndexColumn.setName(portalNewsTree.getName());
		String template;
		//判断是新闻公告还是轮播图
		//新闻公告
		if(path.startsWith("100.")){
			template="<home-news-list classifyId='"+id+"'/>";
			String templateHtml = Base64.getBase64(template);
			sysIndexColumn.setTemplateHtml(templateHtml);
			sysIndexColumn.setColUrl("/newsList/"+id);

			//轮播图
		}else{
			template="<homeCarousel height='"+portalNewsTree.getColHeight()+"' classifyId='"+id+"' :interval='"+portalNewsTree.getIntervalTime()+"'/>";
			String templateHtml = Base64.getBase64(template);
			sysIndexColumn.setTemplateHtml(templateHtml);
		}
		sysIndexColumnManager.create(sysIndexColumn);
		portalNewsTree.setColumnId(suid);
		this.update(portalNewsTree);
		//发布成功后，将授权设置为所有人
		String indexColumnId = sysIndexColumn.getId();
		String objType = "indexColumn";
		String ownerNameJson = "[{\"type\":\"everyone\",\"title\":\"所有人\",\"checked\":true}]";
		sysAuthUserManager.saveRights(indexColumnId,objType,ownerNameJson);
		IUser currentUser = ContextUtil.getCurrentUser();
		sysAuthUserManager.delUserMenuCache(currentUser.getUserId());
		return new CommonResult<>();
	}

	@Override
	public void updateEntity(PortalNewsTree t) throws Exception {
		//首页栏目Id 不为空,则需要同步更新首页栏目
		if(StringUtil.isNotEmpty(t.getColumnId())){
			SysIndexColumn sysIndexColumn = sysIndexColumnManager.get(t.getColumnId());
			if(BeanUtils.isNotEmpty(sysIndexColumn)){
				String path = t.getPath();
				String id = t.getId();
				sysIndexColumn.setColHeight(t.getColHeight().longValue());
				sysIndexColumn.setName(t.getName());
				String template;
				if(path.startsWith("100.")){
					template="<home-news-list classifyId='"+id+"'/>";
					String templateHtml = Base64.getBase64(template);
					sysIndexColumn.setTemplateHtml(templateHtml);

					//轮播图
				}else{
					template="<homeCarousel height='"+t.getColHeight()+"' classifyId='"+id+"' :interval='"+t.getIntervalTime()+"'/>";
					String templateHtml = Base64.getBase64(template);
					sysIndexColumn.setTemplateHtml(templateHtml);
				}
				sysIndexColumnManager.update(sysIndexColumn);
			}

		}
        PortalNewsTree oldData = super.get(t.getId());
        if(BeanUtils.isNotEmpty(oldData) && !oldData.getName().equals(t.getName())){
            LambdaUpdateWrapper<PortalNewsNotice> wrapper = Wrappers.lambdaUpdate();
            wrapper.eq(PortalNewsNotice::getClassifyId,t.getId());
            wrapper.set(PortalNewsNotice::getClassifyName,t.getName());
            portalNewsNoticeManager.update(null,wrapper);
        }
		super.update(t);
	}

	@Override
	public CommonResult<String> mobileIssue(String id) {
		PortalNewsTree portalNewsTree = this.get(id);
		portalNewsTree.setMobileIssue(new BigDecimal(1));
		this.update(portalNewsTree);
		//判断这个分类是不是已经发布了分类,并且这个分类没被删除
		String columnId = portalNewsTree.getColumnId();
		if(StringUtil.isNotEmpty(columnId)){
			SysIndexNewsColumn sysIndexColumn2 = sysIndexNewsColumnManager.getOne(Wrappers.<SysIndexNewsColumn>lambdaQuery().eq(SysIndexNewsColumn::getPortalNewsId, id));
			if(BeanUtils.isNotEmpty(sysIndexColumn2)){
				return new CommonResult<String>(false,"此分类已经被发布成首页栏目,无法再次发布!");
			}
		}
		SysIndexNewsColumn sysIndexColumn=new SysIndexNewsColumn();
		sysIndexColumn.setName(portalNewsTree.getName());
		String path = portalNewsTree.getPath();
		if(path.startsWith("100.")){
			sysIndexColumn.setType("0");
		}else{
			sysIndexColumn.setType("1");
		}
		sysIndexColumn.setPortalNewsId(id);
		sysIndexNewsColumnManager.create(sysIndexColumn);
		return new CommonResult<>("发布成功");
	}

	@Override
	public CommonResult<String> mobileRemove(String id) {
		PortalNewsTree portalNewsTree = this.get(id);
		portalNewsTree.setMobileIssue(new BigDecimal(0));
		this.update(portalNewsTree);
		sysIndexNewsColumnManager.remove(Wrappers.<SysIndexNewsColumn>lambdaQuery().eq(SysIndexNewsColumn::getPortalNewsId, id));
		return new CommonResult<String>("取消公告发布成功");
	}

	//删除时，要把改分类下所属的所有新闻通知全部删掉
	@Override
	@Transactional
	public boolean removeById(Serializable id) {
		PortalNewsTree tree = this.getById(id);
		//顶部分类不允许删除
		if (tree.getParentId().equals("0")) {
			throw new RuntimeException("不允许删除此分类");
		}
		if("2".equals(tree.getRank().toString())){
			//将子分类下的新闻实体删除
			portalNewsNoticeManager.deleteNewsByParentId((String)id);
			//删除已发布的栏目
			sysIndexColumnManager.deleteByNewsParentId((String)id);
			//二级分类，删除该分类下所有子分类
			portalNewsTreeDao.deleteByParentId((String)id);
			//删除已发布的栏目

		}else if("3".equals(tree.getRank().toString())){
			//删除已发布的栏目
			if(StringUtil.isNotEmpty(tree.getColumnId())){
				sysIndexColumnManager.remove(tree.getColumnId());
			}
			//删除新闻实体
			portalNewsNoticeManager.deleteByClassifyId((String)id);


		}
		return super.removeById(id);
	}

	@Override
	public CommonResult<String>  importCheck(String uzPath, String classifyId) throws Exception{
		String fileStr = FileUtil.readFile(uzPath + File.separator + "portalTree.json");
		Map map = JsonUtil.toBean(fileStr, HashMap.class);
		PortalNewsTree targetTree = this.getById(classifyId);//数据导入到这个分类下
		//导入分类
		ArrayList<Object> treesObj = (ArrayList) map.get("trees");
		ArrayList<Object> noticeObj = (ArrayList<Object>)map.get("notices");

		//1、校验分类是否有重复名称(不需要校验分类下内容是否重复，因为分类下内容重复，则分类肯定已经存在，只要分类存在，就会提示覆盖)
		List<String> treeNames = Lists.newArrayList();
		for (Object o : treesObj) {
			PortalNewsTree portalNewsTree = JsonUtil.toBean(JsonUtil.toJson(o), PortalNewsTree.class);
			treeNames.add(portalNewsTree.getName());
		}

		LambdaQueryWrapper<PortalNewsTree> treeQuery = Wrappers.<PortalNewsTree>lambdaQuery().eq(PortalNewsTree::getParentId,classifyId).in(PortalNewsTree::getName, treeNames);
		List<PortalNewsTree> portalNewsList = this.getBaseMapper().selectList(treeQuery);
		if(BeanUtils.isNotEmpty(portalNewsList)){
			//数据库中有重复数据
			return new CommonResult<String>(false, "导入失败，导入的数据中有数据已经存在，是否进行覆盖？");
		}

		//2、没有重复数据，直接导入
		this.importFile(uzPath,classifyId);
		return new CommonResult<String>(true, "导入成功");
	}

	@Override
	@Transactional
	public void importFile(String uzPath, String classifyId)throws Exception {
		try {
			String fileStr = FileUtil.readFile(uzPath + File.separator + "portalTree.json");
			Map map = JsonUtil.toBean(fileStr, HashMap.class);
			PortalNewsTree targetTree = this.getById(classifyId);//数据导入到这个分类下
			//导入分类
			ArrayList<Object> treesObj = (ArrayList) map.get("trees");
			ArrayList<Object> noticeObj = (ArrayList<Object>)map.get("notices");
			List<PortalNewsTree> treesRank2 = new ArrayList<>();
			List<PortalNewsTree> treesRank3 = new ArrayList<>();

			List<PortalNewsNotice> notices = new ArrayList<>();
			for (Object o : treesObj) {
				PortalNewsTree portalNewsTree = JsonUtil.toBean(JsonUtil.toJson(o), PortalNewsTree.class);
				if(2 == portalNewsTree.getRank().intValue()){
					treesRank2.add(portalNewsTree);
				}else if(3 == portalNewsTree.getRank().intValue()){
					treesRank3.add(portalNewsTree);
				}
			}
			//校验分类数据
			if(1 == targetTree.getRank().intValue() && treesRank2.isEmpty()){
				throw new BaseException("不允许在顶级分类中直接导入三级分类,请先添加二级分类");
			}
			if(2 == targetTree.getRank().intValue() && !treesRank2.isEmpty()){
				throw new BaseException("不允许导入同级分类，请选择顶级分类导入");
			}

			if(BeanUtils.isNotEmpty(noticeObj)){
				for (Object o : noticeObj) {
					notices.add(JsonUtil.toBean(JsonUtil.toJson(o), PortalNewsNotice.class));
				}
			}
			if (1 == targetTree.getRank().intValue()) {
				//处理二级菜单
				Map<String, String> changeMap2 = handleTreeRank2(treesRank2, targetTree.getId());
				Map<String, String> changeMap3 = handleTreeRank3(treesRank3, targetTree.getId(), changeMap2);
				handleNotice(notices,changeMap3);
			}else if( 2== targetTree.getRank().intValue()){
				Map<String, String> changeMap3 = handleTreeRank3(treesRank3, targetTree.getId(), new HashMap<>());
				handleNotice(notices,changeMap3);
			}

		}catch (Exception e){
			throw new BaseException(e.getMessage());
		}
	}

	private Map<String,PortalNewsTree> getPortalNewsTreeByNameMap(List<PortalNewsTree> tree,String targetId){
		List<String> treeNames = tree.stream().map(PortalNewsTree::getName).collect(Collectors.toList());
		LambdaQueryWrapper<PortalNewsTree> query = Wrappers.<PortalNewsTree>lambdaQuery().eq(PortalNewsTree::getParentId,targetId).in(PortalNewsTree::getName, treeNames);
		List<PortalNewsTree> portalNewsList = this.getBaseMapper().selectList(query);
		if(BeanUtils.isNotEmpty(portalNewsList)) {
			Map<String, PortalNewsTree> treeMap = portalNewsList.stream().collect(Collectors.toMap(PortalNewsTree::getName, m -> m, (key1, key2) -> key2));
			return treeMap;
		}
		return Maps.newHashMap();
	}

	/**
	 *  处理二级菜单，返回一个map，对应变更前的ID和变更后的ID
	 * @return Map
	 * */
	private Map<String,String> handleTreeRank2(List<PortalNewsTree> trees2,String targetId){

		Map<String, PortalNewsTree> treeMap = this.getPortalNewsTreeByNameMap(trees2, targetId);

		Map<String,String> rtnMap = new HashMap<>();
		for (PortalNewsTree tree : trees2) {
			tree.setParentId(targetId);
			tree.setPath(targetId + "." + tree.getId() + ".");
			PortalNewsTree oldVal = baseMapper.selectById(tree.getId());
			if(BeanUtils.isNotEmpty(oldVal)){
				if(StringUtil.equals(oldVal.getPath(),tree.getPath())){
					baseMapper.updateById(tree);
				}else{
					//在其它路径中存在
					//先判断名称是否有重复
					if(treeMap.containsKey(tree.getName())){
						//有重复，更新覆盖
						String oldId = tree.getId();
						PortalNewsTree portalNewsTree = treeMap.get(tree.getName());
						tree.setId(portalNewsTree.getId());
						tree.setCreateTime(portalNewsTree.getCreateTime());
						rtnMap.put(oldId,portalNewsTree.getId());
						baseMapper.updateById(tree);
					}else {
						//无重复，插入
						String oldId = tree.getId();
						String newId = UniqueIdUtil.getSuid();
						tree.setId(newId);
						tree.setPath(tree.getPath().replace(oldId, newId));
						rtnMap.put(oldId, newId);
						if (saaSConfig.isEnable()) {
							tree.setTenantId(null);
						}
						baseMapper.insert(tree);
					}
				}
			}else{
				if(saaSConfig.isEnable()){
					tree.setTenantId(null);
				}
				baseMapper.insert(tree);
			}
		}
		return rtnMap;
	}

	/**
	 *  处理三级菜单，返回一个map，对应变更前的ID和变更后的ID
	 * @return Map
	 * */
	private Map<String,String> handleTreeRank3(List<PortalNewsTree> tree3, String targetId, Map<String,String> changeMap){
		Map<String,String> rtnMap = new HashMap<>();
		PortalNewsTree parent = this.getById(targetId);
		if(BeanUtils.isEmpty(parent)){
			throw new BaseException("父节点为空");
		}

		Map<String, PortalNewsTree> treeMap = this.getPortalNewsTreeByNameMap(tree3, targetId);

		for (PortalNewsTree tree : tree3) {
			if (changeMap.containsKey(tree.getParentId())) {
				String newPar = changeMap.get(tree.getParentId());
				tree.setParentId(newPar);
				tree.setPath(targetId + "." + newPar + "." + tree.getId() + ".");
			}else if(2 == parent.getRank().intValue()){
				tree.setParentId(targetId);
				tree.setPath(tree.getPath().split("\\.")[0] + "." + targetId + "." + tree.getId() + ".");
			}
			PortalNewsTree oldVal = this.getById(tree.getId());
			if (BeanUtils.isNotEmpty(oldVal)) {
				if(StringUtil.equals(oldVal.getParentId(),tree.getParentId())){
					baseMapper.updateById(tree);
				}else{

					if(treeMap.containsKey(tree.getName())){
						//名称相同，覆盖
						String oldId = tree.getId();
						PortalNewsTree portalNewsTree = treeMap.get(tree.getName());
						tree.setId(portalNewsTree.getId());
						rtnMap.put(oldId,portalNewsTree.getId());
						baseMapper.updateById(tree);
					}else{
						//名称不同，插入
						String oldId = tree.getId();
						String newId = UniqueIdUtil.getSuid();
						tree.setId(newId);
						tree.setPath(tree.getPath().replace(oldId,newId));
						rtnMap.put(oldId,newId);
						if(saaSConfig.isEnable()){
							tree.setTenantId(null);
						}
						baseMapper.insert(tree);
					}
				}
			}else{
				if(saaSConfig.isEnable()){
					tree.setTenantId(null);
				}
				baseMapper.insert(tree);
			}
		}
		return rtnMap;
	}

	/**
	 *  处理公告
	 * */
	private void handleNotice(List<PortalNewsNotice> notices , Map<String,String> changeMap){
		if(BeanUtils.isEmpty(notices)){
			return ;
		}
		for (PortalNewsNotice notice : notices) {
			//获取所在分类
			PortalNewsTree classify;
			String classifyId = notice.getClassifyId();
			if(changeMap.containsKey(classifyId)){
				classifyId = changeMap.get(classifyId);
			}
			classify = baseMapper.selectById(classifyId);
			if(BeanUtils.isEmpty(classify)){
				throw new BaseException("在导入公告【"+notice.getTitle()+"】时所在分类未获取，导入失败");
			}
			notice.setClassifyId(classifyId);
			notice.setClassifyPath(classify.getPath());
			PortalNewsNotice oldVal = portalNewsNoticeManager.getById(notice.getId());
			if(BeanUtils.isNotEmpty(oldVal)){
				if(StringUtil.equals(oldVal.getClassifyPath(), notice.getClassifyPath())){
					portalNewsNoticeManager.updateById(notice);
				}else{
					//判断标题是否存在，存在则覆盖，不存在则插入
					LambdaQueryWrapper<PortalNewsNotice> query = Wrappers.<PortalNewsNotice>lambdaQuery()
							.eq(PortalNewsNotice::getClassifyId, classifyId)
							.eq(PortalNewsNotice::getTitle, notice.getTitle());
					List<PortalNewsNotice> list = this.portalNewsNoticeManager.list(query);
					if(BeanUtils.isNotEmpty(list)){
						PortalNewsNotice portalNewsNotice = list.get(0);
						notice.setId(portalNewsNotice.getId());
						portalNewsNoticeManager.updateById(notice);
					}else {
						notice.setId(UniqueIdUtil.getSuid());
						if(saaSConfig.isEnable()){
							notice.setTenantId(null);
						}
						portalNewsNoticeManager.create(notice);
					}
				}
			}else{
				if(saaSConfig.isEnable()){
					notice.setTenantId(null);
				}
				portalNewsNoticeManager.create(notice);
			}
		}
	}


}
