package com.persagy.proxy.adm.strategy.relationdata;

import java.util.*;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.persagy.dmp.digital.entity.ObjectDigital;
import com.persagy.proxy.adm.constant.AdmCommonConstant;
import com.persagy.proxy.adm.constant.AdmRelationTypeEnum;
import com.persagy.proxy.adm.constant.ObjTypeMapping;
import com.persagy.proxy.report.model.AdmRelationObject;
import com.persagy.proxy.report.service.IRelationReportService;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import org.json.JSONObject;

/**
 * 报表数据抽象类
 * 
 * @version 1.0.0
 * @company persagy 
 * @author zhangqiankun
 * @date 2021年9月2日 下午11:00:26
 */
public abstract class AbstractReportRelationObject extends AbstractRelationObject {

	public AbstractReportRelationObject(IRelationReportService reportDownloadService) {
		super(reportDownloadService);
	}

	@Override
	protected long countRelationObjects(String groupCode, String projectId) {
		throw new UnsupportedOperationException("未实现的策略方法");
	}

	@Override
	protected List<ObjectDigital> queryAllRelations(String groupCode, String projectId, String mainContent, Set<String> slaveContent) {
		throw new UnsupportedOperationException("未实现的策略方法");
	}
	
	@Override
	public List<AdmRelationObject> exportRelationObject(String groupCode, String projectId) {
		List<ObjectDigital> masterObjs = this.queryAllRelations(groupCode, projectId, null, null);
		// 转换中台数据
		return this.handleObjectDigital(masterObjs, groupCode, projectId);
	}
	
	/**
	 * 处理中台响应数据，转换为ADM所需要的数据
	 * 
	 * @param masterObjs
	 * @param groupCode
	 * @param projectId
	 * @return
	 */
	protected List<AdmRelationObject> handleObjectDigital(List<ObjectDigital> masterObjs, String groupCode, String projectId) {
		List<AdmRelationObject> result = new ArrayList<AdmRelationObject>();
		// 遍历所有主对象
		for (ObjectDigital master : masterObjs) {
			List<ObjectDigital> slaveObjs = master.getRelObjs();
			if (CollectionUtil.isEmpty(slaveObjs)) {
				continue;	// 从对象不存在的，不再返回主对象数据
			}
			
			// 遍历所有的从对象
			for (ObjectDigital slave : slaveObjs) {
				result.add(this.handleObjectDigital(master, slave, groupCode, projectId));
			}
		}
		
		return result;
	}
	
	/**
	 * 处理中台对象，返回前端所需要的
	 * 
	 * @param master
	 * @param slave
	 * @param groupCode
	 * @param projectId
	 * @return
	 */
	protected abstract AdmRelationObject handleObjectDigital(ObjectDigital master, ObjectDigital slave, String groupCode, String projectId);

	/**
	 * 封装响应数据，具体的传值，请仔细侦查，这里仅返回共有字段，特殊字段，自行赋值
	 * 
	 * @param master
	 * @param masterType
	 * @param slave
	 * @param slaveType
	 * @return
	 */
	protected AdmRelationObject convertObject(ObjectDigital master, String masterType, ObjectDigital slave, String slaveType) {
		AdmRelationObject relationObject = new AdmRelationObject();
		
		// ID
		String masterId = master.getId();
		relationObject.setMasterCode(masterId);
		relationObject.setMasterId(masterId);
		// 图纸编码
		ObjectNode masterInfos = master.getInfos();
		relationObject.setMasterCadId(masterInfos.get("cADID") == null ? AdmCommonConstant.EMPTY  : masterInfos.get("cADID").asText());
		// 名称
		relationObject.setMasterName(master.getName());
		// 本地ID
		relationObject.setMasterLocalId(master.getLocalId());
		// 本地名称
		relationObject.setMasterLocalName(master.getLocalName());
		// 类型
		relationObject.setMasterType(masterType);
		
		// ID
		String slaveId = slave.getId();
		relationObject.setSlaveCode(slaveId);
		relationObject.setSlaveId(slaveId);
		// 图纸编码
		ObjectNode slaveInfos = slave.getInfos();
		relationObject.setSlaveCadId(slaveInfos.get("cADID") == null ? AdmCommonConstant.EMPTY  : slaveInfos.get("cADID").asText());
		// 名称
		relationObject.setSlaveName(slave.getName());
		// 本地ID
		relationObject.setSlaveLocalId(slave.getLocalId());
		// 本地名称
		relationObject.setSlaveLocalName(slave.getLocalName());
		// 类型
		relationObject.setSlaveType(slaveType);
		
		return relationObject;
	}
	
	/**
	 * 检查关系对象数据的正确性，并完成额外字段的赋值功能
	 * 
	 * @param relationObject
	 * @param relationTypeEnum AdmRelationTypeEnum枚举类
	 * @param code
	 * @return String - 校验失败的原因， ObjectNode -- BDTP接口的参数，不会返回null，请用instanceOf 判断返回值
	 */
	protected Object beforeSaveRelationObject(AdmRelationObject relationObject, AdmRelationTypeEnum relationTypeEnum,
			String groupCode, String projectId, String code) {
		if (!StrUtil.isAllNotBlank(relationObject.getMasterCode(), relationObject.getSlaveCode())) {
			return "主对象或从对象的识别编码为空";
		}
		/*if (!StrUtil.isAllNotBlank(relationObject.getMasterId(), relationObject.getSlaveId())) {
			return "主对象或从对象的ID为空";
		}*/
		
		// 获取备用的类型
		String relationType = relationTypeEnum.getRelationType();
		int indexOf = relationType.indexOf("_");
		String relCodeBak = indexOf > 0 ? relationType.substring(0, indexOf) : relationType;
		
		String relCode = relationTypeEnum.getRelCode();
		String relCodePrefix = ObjTypeMapping.getRelCodePrefix(relCode);
		String masterObjType = ObjTypeMapping.PREFIX_FULLNAME.get(relCodePrefix);
		if (StrUtil.isBlank(masterObjType)) {
			relCodePrefix = ObjTypeMapping.getRelCodePrefix(relCodeBak);
			relCodePrefix = StrUtil.upperFirst(relCodePrefix);
			masterObjType = ObjTypeMapping.PREFIX_FULLNAME.get(relCodePrefix);
			if (StrUtil.isBlank(masterObjType)) {
				return "边类型错误";
			}
		}
		String slaveObjType = ObjTypeMapping.PREFIX_FULLNAME.get(ObjTypeMapping.getRelCodeSuffix(relCode));
		if (StrUtil.isBlank(slaveObjType)) {
			String relCodeSuffix = StrUtil.upperFirst(ObjTypeMapping.getRelCodeSuffix(relCodeBak));
			slaveObjType = ObjTypeMapping.PREFIX_FULLNAME.get(relCodeSuffix);
			if (StrUtil.isBlank(slaveObjType)) {
				return "边类型错误";
			}
		}
		// 查询出对象信息
		List<ObjectNode> masters = this.relationReportService.findObjectNodes(groupCode, projectId, masterObjType, code, relationObject.getMasterCode());
		if (CollectionUtil.isEmpty(masters)) {
			return "未找到主对象";
		}
		if (masters.size() > 1) {
			return "匹配到多个主对象";
		}
		// 查询出从对象
		List<ObjectNode> slaves = this.relationReportService.findObjectNodes(groupCode, projectId, slaveObjType, code, relationObject.getSlaveCode());
		if (CollectionUtil.isEmpty(slaves)) {
			return "未找到从对象";
		}
		if (masters.size() > 1) {
			return "匹配到多个从对象";
		}
		
		// 添加关系数据
		ObjectNode master = masters.get(0);
		ObjectNode slave = slaves.get(0);
		String masterClassCode = master.get("classCode") == null ? AdmCommonConstant.EMPTY : master.get("classCode").asText();
		String slaveClassCode = slave.get("classCode") == null ? AdmCommonConstant.EMPTY : slave.get("classCode").asText();
		
		String result = this.checkRelationObject(master, masterClassCode, slave, slaveClassCode);
		if (StrUtil.isBlank(result)) {
			ObjectNode objectNode = OBJECT_MAPPER.createObjectNode();
			String graphCode = relationTypeEnum.getGraphCode();
			objectNode.put("graphId", "Gt" + graphCode + "001");
			objectNode.put("graphCode", graphCode);
			objectNode.put("relCode", relCode);
			if ("Sp".equals(relCodePrefix)) {
				objectNode.put("relValue", masterClassCode);
			}
			objectNode.put("objFrom", master.get("id").asText());
			objectNode.put("objTo", slave.get("id").asText());
			return objectNode;
		}
		return result; 
	}

	/**
	 * 检查关系对象数据的正确性，并完成额外字段的赋值功能
	 *
	 * @param relationTypeEnum AdmRelationTypeEnum枚举类
	 * @param code
	 * @return String - 校验失败的原因， ObjectNode -- BDTP接口的参数，不会返回null，请用instanceOf 判断返回值
	 */
	protected Map<String,Object> beforeSaveRelationObjects(List<AdmRelationObject> relationObjects, AdmRelationTypeEnum relationTypeEnum,
														   String groupCode, String projectId, String code) {
		Map<String, Object> result = new HashMap<>();
		if (CollUtil.isEmpty(relationObjects)){
			return CollUtil.newHashMap(0);
		}
		// 收集master的识别编码
		Set<String> masterCodes = new HashSet<>();
		Set<String> masterObjTypes = new HashSet<>();
		// 收集slave的识别编码
		Set<String> slaveCodes = new HashSet<>();
		Set<String> slaveObjTypes = new HashSet<>();
		for (AdmRelationObject relationObject : relationObjects) {
			if (!StrUtil.isAllNotBlank(relationObject.getMasterCode(), relationObject.getSlaveCode())) {
				result.put(StrUtil.toString(relationObject.getMasterCode())+StrUtil.UNDERLINE
						+StrUtil.toString(relationObject.getSlaveCode()),"主对象或从对象的识别编码为空");
				continue;
			}
			// 获取备用的类型
			String relationType = relationTypeEnum.getRelationType();
			int indexOf = relationType.indexOf("_");
			String relCodeBak = indexOf > 0 ? relationType.substring(0, indexOf) : relationType;
			String relCode = relationTypeEnum.getRelCode();
			String relCodePrefix = ObjTypeMapping.getRelCodePrefix(relCode);
			String masterObjType = ObjTypeMapping.PREFIX_FULLNAME.get(relCodePrefix);
			if (StrUtil.isBlank(masterObjType)) {
				relCodePrefix = ObjTypeMapping.getRelCodePrefix(relCodeBak);
				relCodePrefix = StrUtil.upperFirst(relCodePrefix);
				masterObjType = ObjTypeMapping.PREFIX_FULLNAME.get(relCodePrefix);
				if (StrUtil.isBlank(masterObjType)) {
					result.put(relationObject.getMasterCode()+StrUtil.UNDERLINE +relationObject.getSlaveCode(),"边类型错误");
					continue;
				}
			}
			String slaveObjType = ObjTypeMapping.PREFIX_FULLNAME.get(ObjTypeMapping.getRelCodeSuffix(relCode));
			if (StrUtil.isBlank(slaveObjType)) {
				String relCodeSuffix = StrUtil.upperFirst(ObjTypeMapping.getRelCodeSuffix(relCodeBak));
				slaveObjType = ObjTypeMapping.PREFIX_FULLNAME.get(relCodeSuffix);
				if (StrUtil.isBlank(slaveObjType)) {
					result.put(relationObject.getMasterCode()+StrUtil.UNDERLINE +relationObject.getSlaveCode(),"边类型错误");
					continue;
				}
			}
			if (StrUtil.isBlank(code)
					|| !RelationObjectStrategy.OBJNAME_2_TYPE.containsKey(code)
					|| StrUtil.isBlank(RelationObjectStrategy.OBJNAME_2_TYPE.get(code))) {
				result.put(relationObject.getMasterCode()+StrUtil.UNDERLINE +relationObject.getSlaveCode(),"未找到主对象");
				continue;
			}
			masterCodes.add(relationObject.getMasterCode());
			slaveCodes.add(relationObject.getSlaveCode());
			masterObjTypes.add(masterObjType);
			slaveObjTypes.add(slaveObjType);
		}
		if (StrUtil.isBlank(code)
				|| !RelationObjectStrategy.OBJNAME_2_TYPE.containsKey(code)
				|| StrUtil.isBlank(RelationObjectStrategy.OBJNAME_2_TYPE.get(code))
				|| CollUtil.isEmpty(masterCodes)
				|| CollUtil.isEmpty(slaveCodes)
				|| CollUtil.isEmpty(masterObjTypes)
				|| CollUtil.isEmpty(slaveObjTypes)) {
			return result;
		}
		// 查询出对象信息
		Map<String,List<ObjectNode>> masterMap = this.relationReportService.findObjectNodesByPage(groupCode, projectId,
				masterObjTypes, RelationObjectStrategy.OBJNAME_2_TYPE.get(code), masterCodes);
		Map<String,List<ObjectNode>> slaveMap = this.relationReportService.findObjectNodesByPage(groupCode, projectId,
				slaveObjTypes, RelationObjectStrategy.OBJNAME_2_TYPE.get(code), slaveCodes);
		String relationType = relationTypeEnum.getRelationType();
		int indexOf = relationType.indexOf("_");
		String relCodeSuffix = StrUtil.upperFirst(ObjTypeMapping
				.getRelCodeSuffix(indexOf > 0 ? relationType.substring(0, indexOf) : relationType));
		for (AdmRelationObject relationObject : relationObjects) {
			String key = StrUtil.toString(relationObject.getMasterCode())+StrUtil.UNDERLINE
					+StrUtil.toString(relationObject.getSlaveCode());
			if (result.containsKey(key)){
				continue;
			}
			List<ObjectNode> masterNodes = masterMap.get(relationObject.getMasterCode());
			if (CollectionUtil.isEmpty(masterNodes)) {
				result.put(relationObject.getMasterCode()+StrUtil.UNDERLINE +relationObject.getSlaveCode(),"未找到主对象");
				continue;
			}
			if (masterNodes.size() > 1) {
				result.put(relationObject.getMasterCode()+StrUtil.UNDERLINE +relationObject.getSlaveCode(),"匹配到多个主对象");
				continue;
			}
			List<ObjectNode> slaveNodes = slaveMap.get(relationObject.getSlaveCode());
			if (CollectionUtil.isEmpty(slaveNodes)) {
				result.put(relationObject.getMasterCode()+StrUtil.UNDERLINE +relationObject.getSlaveCode(),"未找到从对象");
				continue;
			}
			if (slaveNodes.size() > 1) {
				result.put(relationObject.getMasterCode()+StrUtil.UNDERLINE +relationObject.getSlaveCode(),"匹配到多个从对象");
				continue;
			}
			// 添加关系数据
			ObjectNode master = masterNodes.get(0);
			ObjectNode slave = slaveNodes.get(0);
			String masterClassCode = master.get("classCode") == null ? AdmCommonConstant.EMPTY : master.get("classCode").asText();
			String slaveClassCode = slave.get("classCode") == null ? AdmCommonConstant.EMPTY : slave.get("classCode").asText();
			String subResult = this.checkRelationObject(master, masterClassCode, slave, slaveClassCode);
			if (StrUtil.isBlank(subResult)) {
				ObjectNode objectNode = OBJECT_MAPPER.createObjectNode();
				String graphCode = relationTypeEnum.getGraphCode();
				objectNode.put("graphId", "Gt" + graphCode + "001");
				objectNode.put("graphCode", graphCode);
				objectNode.put("relCode", relationTypeEnum.getRelCode());
				if ("Sp".equals(relCodeSuffix)) {
					objectNode.put("relValue", masterClassCode);
				}
				objectNode.put("objFrom", master.get("id").asText());
				objectNode.put("objTo", slave.get("id").asText());
				result.put(relationObject.getMasterCode()+StrUtil.UNDERLINE +relationObject.getSlaveCode(),objectNode);
			}
		}
		return result;
	}

	/**
	 * 检查关系对象数据的正确性，并可完成额外字段的赋值功能
	 * 默认不实现，由子类实现
	 * 
	 * @param master
	 * @param masterClassCode
	 * @param slave
	 * @param slaveClassCode
	 * @return 当为null时，检查通过，否则失败，返回失败原因
	 */
	protected String checkRelationObject(ObjectNode master, String masterClassCode, ObjectNode slave, String slaveClassCode) {
		return null;
	}

}
