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

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.stream.Collectors;

import org.springblade.bi.client.model.CubeDataModel;
import org.springblade.bi.client.model.DataSourceModel;
import org.springblade.cube.enums.ViewColumnTypeEnum;
import org.springblade.flow.util.JsonUtil;
import org.springblade.flow.visual.base.entity.VisualdevEntity;
import org.springblade.flow.visual.onlinedev.common.dynamic.DataSourceService;
import org.springblade.flow.visual.onlinedev.common.dynamic.DynamicDataService;
import org.springblade.flow.visual.onlinedev.common.excel.ExcelFormParam.ExcelFieldIndex;
import org.springblade.flow.visual.onlinedev.common.formdata.FormDataWithTableService;
import org.springblade.flow.visual.onlinedev.common.relation.RelationField;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.github.xiaoymin.knife4j.core.util.StrUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * 单表excel导入
 * 
 * @author william
 * @date 2022年9月15日 下午3:39:36
 */
@Slf4j
public class ExcelRead4SingleTableListener extends AnalysisEventListener<LinkedHashMap<Integer, String>> {
	private static final int BATCH_COUNT = 10000;

	private long total;

	private List<LinkedHashMap<Integer, String>> dataList = new ArrayList<>();

	private DataSourceModel ds;
	private List<ExcelFieldIndex> indexList;

	private String insertSql;
	private LinkedHashMap<Integer, ViewColumnTypeEnum> headerMap;
	private DynamicDataService dynamicDataService;
	private boolean hasKey = false;

	public ExcelRead4SingleTableListener(FormDataWithTableService formDataWithTableService,
			DataSourceService dataSourceService, CubeDataModel cubeData, DynamicDataService dynamicDataService,
			DataSourceModel ds, VisualdevEntity formInfo, List<ExcelFieldIndex> sourceIndexList) throws SQLException {
		this.dynamicDataService = dynamicDataService;
		this.ds = ds;

		headerMap = new LinkedHashMap<>();

		String tables = formInfo.getTables();
		List<RelationField> fieldList = JsonUtil.getJsonToList(tables, RelationField.class);
		RelationField first = fieldList.get(0);

		String key = formDataWithTableService.getKey(ds, first.getTableName());

		// insert into t1(field1,field2) values(?,?);
		StringBuffer fieldBuffer = new StringBuffer();
		fieldBuffer.append("insert into " + first.getTableName() + "(");

		StringBuffer valueBuffer = new StringBuffer();
		valueBuffer.append(" values(");

		// 按照excel索引升序排列
		this.indexList = sourceIndexList.stream().sorted(Comparator.comparing(ExcelFieldIndex::getIndex))
				.collect(Collectors.toList());
		for (int i = 0, size = indexList.size(); i < size; i++) {
			ExcelFieldIndex fieldIndex = indexList.get(i);
			RelationField field = getByFieldId(fieldList, fieldIndex.getFieldId());
			fieldBuffer.append(field.getField());
			valueBuffer.append("?");
			if (i < size - 1) {
				fieldBuffer.append(",");
				valueBuffer.append(",");
			}
			ViewColumnTypeEnum type = ViewColumnTypeEnum.valueOf(field.getDataTypeOrigin());
			headerMap.put(fieldIndex.getIndex(), type);
		}

		if (StrUtil.isNotBlank(key)) {
			// 如果该表有主键
			hasKey = true;
			fieldBuffer.append("," + key);

			valueBuffer.append(",?");

			headerMap.put(9999, ViewColumnTypeEnum.STRING);
		}

		fieldBuffer.append(")");
		valueBuffer.append(")");

		insertSql = fieldBuffer.toString() + valueBuffer.toString();
	}

	private RelationField getByFieldId(List<RelationField> fieldList, int fieldId) {
		for (RelationField field : fieldList) {
			if (field.getFieldId() == fieldId) {
				return field;
			}
		}

		return null;
	}

	@Override
	public void invoke(LinkedHashMap<Integer, String> data, AnalysisContext context) {
		LinkedHashMap<Integer, String> temp = new LinkedHashMap<>();
		for (ExcelFieldIndex fieldIndex : indexList) {
			Integer index = fieldIndex.getIndex();
			temp.put(index, data.get(index));
		}
		if (hasKey) {
			temp.put(9999, IdWorker.getIdStr());
		}
		dataList.add(temp);

		if (dataList.size() >= BATCH_COUNT) {
			saveData();
			// 存储完成清理 list
			dataList.clear();
		}
	}

	@Override
	public void doAfterAllAnalysed(AnalysisContext context) {
		saveData();
		log.info("所有数据解析完成！");
	}

	/**
	 * 将数据存储数据库
	 */
	private void saveData() {
		log.info("insert sql is:" + insertSql);
		dynamicDataService.batchSave(ds, insertSql, BATCH_COUNT, headerMap, dataList);
		total += dataList.size();
		log.info("存储数据库成功！");
	}

	public long getTotal() {
		return total;
	}
}
