package org.springblade.flow.visual.onlinedev.common.dynamic;

import java.util.HashMap;
import java.util.List;

import org.springblade.bi.client.CubeDataClient;
import org.springblade.bi.client.CubeTableColumnClient;
import org.springblade.bi.client.DataSourceClient;
import org.springblade.bi.client.model.CubeDataModel;
import org.springblade.bi.client.model.CubeTableColumnModel;
import org.springblade.bi.client.model.DataSourceModel;
import org.springblade.cube.dto.TableLinkJoin;
import org.springblade.cube.dto.TableLinkJoin.JoinKey;
import org.springblade.flow.database.model.DbLinkEntity;
import org.springblade.flow.util.JsonUtil;
import org.springblade.flow.visual.onlinedev.common.enums.DsType;
import org.springblade.flow.visual.onlinedev.common.relation.RelationBean;
import org.springblade.flow.visual.onlinedev.common.relation.RelationUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.hutool.core.collection.CollUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 数据集操作
 * 
 * @author william
 * @date 2022年8月19日 下午2:46:01
 */
@Slf4j
@Service
public class DataSourceService {

	@Autowired
	private CubeDataClient cubeDataClient;

	@Autowired
	private DataSourceClient dataSourceClient;

	@Autowired
	private CubeTableColumnClient tableColumnClient;

	/**
	 * 根据表单提交的字段和表信息  组装表关联的树形结构
	 * 
	 * @param tablesJson 表单提交的字段和表信息
	 * @param cubeId 数据集ID
	 * @return
	 */
	public List<RelationBean> getRelationTree(String tablesJson, String cubeId) {
		CubeDataModel cubeData = cubeDataClient.getById(Integer.decode(cubeId));
		List<RelationBean> list = RelationUtil.rebuild(tablesJson, cubeData);
		List<RelationBean> tree = RelationUtil.rebuildTreeRalation(list);
		return tree;
	}

	/**
	 * 递归入库时向下传递子表需要的关联关系 和 关联字段对应的值
	 * 
	 * @param cubeData 数据集
	 * @param parentTable 父表名
	 * @param parentData 父表入库的数据
	 * @return
	 */
	public HashMap<String, HashMap<String, Object>> getParentTableRelationData(CubeDataModel cubeData,
			String parentTable, HashMap<String, Object> parentData) {
		List<TableLinkJoin> joinList = JsonUtil.getJsonToList(cubeData.getLinksJoin(), TableLinkJoin.class);
		// 子表名称，子表字段，子表对应的要入库的父表关联字段的值
		// HashMap<ChildTableName,HashMap<ChildFieldName,SourceData>>
		HashMap<String, HashMap<String, Object>> map = new HashMap<>();
		if (CollUtil.isEmpty(joinList) || CollUtil.isEmpty(parentData)) {
			// 不存在关联关系，直接返回
			log.info("no join relation");
			return map;
		}

		for (TableLinkJoin join : joinList) {
			if (join.getSource().equalsIgnoreCase(parentTable)) {
				// 存在关联关系
				String childTable = join.getTarget();
				HashMap<String, Object> childMap = new HashMap<>();

				List<JoinKey> joinKeys = join.getJoinKeys();
				if (CollUtil.isEmpty(joinKeys)) {
					continue;
				}

				for (JoinKey key : joinKeys) {
					if (key.isTargetKeyVtState() || key.isSourceKeyVtState()) {
						// 虚拟字段，忽略
						continue;
					} else {
						String parentField = key.getSourceKey();
						String childField = key.getTargetKey();
						if (parentData != null && parentData.containsKey(parentField)) {
							Object sourceData = parentData.get(parentField);
							childMap.put(childField, sourceData);
						}
					}
				}
				map.put(childTable, childMap);
			}
		}
		return map;
	}

	/**
	 * 根据数据集ID
	 * 
	 * @param cubeId 数据集ID
	 * @return
	 */
	public List<TableLinkJoin> getTableLinkJoinList(String cubeId) {
		CubeDataModel cubeData = cubeDataClient.getById(Integer.decode(cubeId));
		List<TableLinkJoin> joinList = JsonUtil.getJsonToList(cubeData.getLinksJoin(), TableLinkJoin.class);
		return joinList;
	}

	/**
	 * 查询数据源连接信息
	 * 
	 * @param cubeId 数据集ID
	 * @return
	 */
	public DataSourceModel getReportDatasource(String cubeId) {
		CubeDataModel cubeData = cubeDataClient.getById(Integer.decode(cubeId));
		if (cubeData != null) {
			return dataSourceClient.getById(cubeData.getDatasourceId());
		}
		return null;
	}

	/**
	 * 查询数据集信息
	 * 
	 * @param cubeId 数据集ID
	 * @return
	 */
	public CubeDataModel getCubeData(String cubeId) {
		CubeDataModel cubeData = null;
		try {
			cubeData = cubeDataClient.getById(Integer.decode(cubeId));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return cubeData;
	}

	public DbLinkEntity getInfo(String cubeId) {
		CubeDataModel cubeData = cubeDataClient.getById(Integer.decode(cubeId));
		if (cubeData != null) {
			DataSourceModel source = dataSourceClient.getById(cubeData.getDatasourceId());
			return convertToDbLink(source);
		}
		return null;
	}

	private DbLinkEntity convertToDbLink(DataSourceModel source) {
		if (source == null) {
			log.info("CubeService::convertToDbLink the reportDatasource is null");
			return null;
		}

		DbLinkEntity link = new DbLinkEntity();
		link.setDbSchema(source.getDsUser());
		link.setDbType(DsType.reslove(source.getDsType()).name());
		link.setDescription(source.getRemark());
		link.setFullName(source.getPoolName());
		link.setHost(source.getDsIp());
		link.setPort(source.getDsPort());
		link.setId(source.getId() + "");
		link.setPassword(source.getDsPassword());
		link.setServiceName(source.getDsDb());
		link.setUserName(source.getDsUser());
		link.setUrl(source.getUrl());
		return link;
	}

	/**
	 * 根据字段ID获取字段信息对象
	 */
	public CubeTableColumnModel getFieldInfo(int id) {
		return tableColumnClient.getById(id);
	}

	/**
	 * 根据字段ID获取字段真实名称，例如：COL_2
	 * 
	 * @param id
	 * @return
	 */
	public String getField(int id) {
		CubeTableColumnModel column = getFieldInfo(id);
		if (column != null) {
			return column.getColumnName();
		}
		return null;
	}
}
