import { Modal } from 'antd';
import { giveFilePostDataInfoForTrue } from '@/webPublic/one_stop_public/Base16';
import { queryOauthActionPath } from '@/webPublic/one_stop_public/utils/queryConfig';
import { getToken } from '@/webPublic/one_stop_public/utils/token';
import { deepCopy } from '@/webPublic/zyd_public/utils/utils';
import { getTransformApi } from '@/webPublic/one_stop_public/2022beidianke/localstorageTransform';
import moment from 'moment';
import { getSassApiHeader } from '@/webPublic/one_stop_public/2023yunshangguizhou/utils';
import { showDownloadProgressFromFileName, showDownloadProgressFromCacheKey } from './utils';

const apiUrl = queryOauthActionPath();
export { apiUrl };
const exportStyles = {
	header: {
		font: {
			bold: false,
			fontHeightInPoints: 12,
		},
		alignment: 'CENTER',
		borderLeft: 'THIN',
		borderTop: 'THIN',
		borderBottom: 'THIN',
		borderRight: 'THIN',
		verticalAlignment: 'CENTER', //TOP、CENTER、BOTTOM、JUSTIFY、DISTRIBUTED
		wrapText: true,
		rowHeights: 20,
		colWidths: 250,
	},
	head: {
		font: {
			bold: true,
		},
		alignment: 'CENTER',
	},
};

const uj = {
	t: 1,
	v: '序号',
	s: 'header',
	w: 20, //默认值是20像素
};
/**
 * 公共函数代码
 *
 * */

/**
 * 列表获取纵向合并数据
 * mergeKey : 需要合并的表头key
 * data : 列表数据
 * eliminateRow : 列需要忽略合并的数据
 * eliminateCol : 行需要忽略合并的数据
 *
 * 返回值
 * rowSpanData 列合并数据，colSpanData行合并数据
 * */
export function getSpanJson({
	mergeKey = [],
	data,
	eliminateRow = [],
	eliminateCol = [],
	mergePrimaryRow,
	mergeMappingRow = {}, // 某一列的合并数据 复制 到任意其他列
}) {
	const dataList = deepCopy(data);
	let rowSpanData,
		colSpanData = null;
	try {
		rowSpanData = getRowSpanJson(mergeKey, dataList, eliminateRow, mergePrimaryRow);
	} catch (err) {
		console.table('rowSpanData', err);
	}
	try {
		colSpanData = getColSpanJson(mergeKey, dataList, eliminateCol);
	} catch (err) {
		console.table('colSpanData', err);
	}
	try {
		const newMergeMappingRow = Object.keys(mergeMappingRow).filter((item1) =>
			mergeKey.some((item2) => item2 === item1),
		);
		newMergeMappingRow.map((item) => {
			const mappingList = mergeMappingRow[item].filter(
				(item1) => !mergeKey.some((item2) => item2 === item1),
			);
			mappingList.map((mItem) => {
				rowSpanData[mItem] = rowSpanData[item];
			});
		});
	} catch (e) {
		console.table('mergeMappingRow', e);
	}
	return {
		rowSpanData,
		colSpanData,
	};
}

function getRowSpanJson(cloumnNames, data, eliminateStr = [], mergePrimaryRow) {
	data = deepCopy(data);
	//纵向合并
	// 获取列的 dataIndex 集合
	var rowSpanJson = {};
	//保存上一个name
	var beforeNameMap = {};
	//相同name出现的次数
	var countMap = {};
	//该name第一次出现的位置
	var startIndexMap = {};
	// 是否主键模式
	var isPrimary = false;
	for (var idx = 0; idx < data.length; idx++) {
		// 循环数据
		var dataItem = data[idx];
		var dataItemRowValue;
		var dataItemPreviousRowValue;
		if (mergePrimaryRow) {
			isPrimary = true; //开启主键模式
			dataItemRowValue = dataItem[mergePrimaryRow];
			dataItemPreviousRowValue = data[idx - 1 > 0 ? idx - 1 : 0][mergePrimaryRow];
		}
		for (var idj = 0; idj < cloumnNames.length; idj++) {
			// 循环表头
			var keyItem = cloumnNames[idj];
			var dataItemValue = dataItem[keyItem];
			if (idx === 0) {
				beforeNameMap[keyItem] = dataItemValue;
				countMap[keyItem] = 1;
				startIndexMap[keyItem] = 0;
				rowSpanJson[keyItem] = new Array(data.length);
				rowSpanJson[keyItem][0] = 1;
				continue;
			}
			if (
				(!isPrimary
					? dataItemValue === beforeNameMap[keyItem]
					: dataItemRowValue + dataItemValue ===
					  dataItemPreviousRowValue + beforeNameMap[keyItem]) && // 与上一个值一致时
				eliminateStr.indexOf(dataItemValue) === -1 // 排除特定的值合并
			) {
				countMap[keyItem] = countMap[keyItem] + 1;
				rowSpanJson[keyItem][startIndexMap[keyItem]] = countMap[keyItem];
				rowSpanJson[keyItem][idx] = 0;
			} else {
				countMap[keyItem] = 1;
				beforeNameMap[keyItem] = dataItemValue;
				startIndexMap[keyItem] = idx;
				rowSpanJson[keyItem][idx] = 1;
			}
		}
	}
	return rowSpanJson;
}

function getColSpanJson(cloumnNames, data, eliminateStr = []) {
	data = deepCopy(data);
	//横向合并
	var colSpanJson = {};
	for (let idx = 0; idx < data.length; idx++) {
		let dataItem = data[idx];
		let colSum = 1; //宽度
		let triggerColIndex = null; //记录触发时得位置
		let triggerColSum = 1; //记录触发时得位置
		let isCol = false;
		for (let idj = 0; idj < cloumnNames.length; idj++) {
			let keyItem = cloumnNames[idj];
			let dataItemValue = dataItem[keyItem];
			let dataItemValueNext = idj < cloumnNames.length - 1 ? dataItem[cloumnNames[idj + 1]] : null;
			if (idx === 0) {
				colSpanJson[keyItem] = new Array(data.length);
			}
			if (
				!isCol &&
				dataItemValue === dataItemValueNext &&
				eliminateStr.indexOf(dataItemValue) === -1
			) {
				//触发合并
				triggerColIndex = keyItem;
				isCol = true;
			}
			if (isCol && (dataItemValue !== dataItemValueNext || dataItemValueNext == null)) {
				//合并结束
				isCol = false;
			}
			if (isCol) {
				//计数
				triggerColSum++;
			}
			if (!isCol && triggerColIndex !== null) {
				colSpanJson[triggerColIndex][idx] = triggerColSum;
				colSpanJson[keyItem][idx] = 0;
				triggerColIndex = null;
			} else if (isCol && triggerColIndex !== null) {
				colSpanJson[keyItem][idx] = 0;
			} else {
				colSpanJson[keyItem][idx] = colSum;
			}
		}
	}
	return colSpanJson;
}

/**
 * ant表头转换成二维数组对象。
 * columns : ant的表头
 *
 * 返回值
 * columnsList 基础数据
 * columnsMerges 合并数据
 * columnsKey key对应的列
 * columnsHeight 行数
 * */
export function getColumns(columns) {
	columns = deepCopy(columns);
	let columnsHeight = getColumnsMaxLevel(columns); //递归行数
	let columnsKey = [];
	const columnsList = new Array(columnsHeight).fill([]);
	let col = 1;
	for (var i in columnsList) {
		columnsList[i] = new Array(getColumnsWidth(columns)).fill({});
	}

	function getColumnsDatas(data = [], res = [], level = 1) {
		try {
			for (let item of data) {
				//item.key = i;
				let isLast = !item.children;
				item.level = level;
				item.isLast = isLast;
				item.width = !isLast ? getColumnsWidth(item.children) : 1;
				item.col = col;
				res.push(item);
				columnsList[level - 1][col - 1] = {
					...uj,
					v: item.title,
				};
				if (!isLast) {
					if (Array.isArray(item.children)) {
						let x = level + 1;
						getColumnsDatas(item.children, res, x);
					}
				} else {
					col++;
					columnsKey.push(item['dataIndex']);
				}
			}
			return res;
		} catch (e) {
			console.table('getColumnsDatas', e);
			return [];
		}
	}

	//递归行数
	function getColumnsMaxLevel(arr = []) {
		//递归计算树形数据最大的层级数
		let maxLevel = 0;
		(function multiArr(arr, level = 0) {
			++level;
			maxLevel = Math.max(level, maxLevel);
			for (let i = 0; i < arr.length; i++) {
				let item = arr[i];
				item.level = level;
				if (item.children && item.children.length > 0) {
					multiArr(item.children, level);
				} else {
					delete item.children;
				}
			}
		})(arr, 0);
		return maxLevel;
	}

	//递归当前数据宽度
	function getColumnsWidth(data = [], sum = 0) {
		for (let item of data) {
			if (!item.children) {
				sum++;
			} else {
				sum = getColumnsWidth(item.children, sum);
			}
		}
		return sum;
	}

	let columnsHandle = getColumnsDatas(columns).filter((v, i) => {
		return (v.level < columnsHeight && v.isLast) || v.width > 1;
	});
	let columnsMerges = [];
	columnsHandle.forEach((v, i) => {
		let { isLast, width, col, level } = v;
		let nowCol = col - 1;
		let nowLevel = level - 1;
		if (isLast && width === 1) {
			//合并表格的 开始行、结束行、开始列、结束列
			columnsMerges.push([nowLevel, columnsHeight - 1, nowCol, nowCol]);
		}
		if (!isLast && width > 1) {
			columnsMerges.push([nowLevel, nowLevel, nowCol, nowCol + width - 1]);
		}
	});
	return {
		columnsList,
		columnsMerges,
		columnsKey,
		columnsHeight,
	};
}

/**
 *
 * @param {sqlKey,columns,styles,fileName,ext,allValues} param
 * 表头和sql数据导出（表头合并表格，数据不合并表格）
 * sqlKey : 数据sql编码
 * columns : ant表头基础数据
 * styles : 导出excl样式
 * fileName : 导出文件名
 * ext : 导出后缀 目前xecl、dbf
 * url : 接口地址
 */
export function getColumnsSqlKeyRealize({
	sqlKey,
	columns,
	styles,
	fileName = '导出文件',
	ext = 'xlsx',
	allValues = JSON.stringify({}),
}) {
	columns = deepCopy(columns);

	let { columnsList, columnsMerges, columnsKey } = getColumns(columns);

	let content = {
		sheets: [
			{
				name: fileName,
				cells: columnsList,
				merges: columnsMerges,
				sqlKey: sqlKey, //sql编码
				sqlKeyHeader: columnsKey, //sql对应key对应列
			},
		],
		styles: exportStyles,
	};
	if (styles) {
		content.styles = styles;
	}
	try {
		let getFileData = giveFilePostDataInfoForTrue(
			{
				content: JSON.stringify(content),
				title: fileName,
				allValues: allValues,
			},
			`${apiUrl + '/DataObjApi/exportCustom'}`,
		);
		let token = getToken();
		downloadFile(
			getFileData.url,
			{
				...getFileData.datas,
				token: token,
			},
			fileName,
			ext,
		);
	} catch (err) {
		console.table('getColumnsSqlKeyRealize', err);
	}
}

/**
 *
 * @param {sqlKey,columnsList,columnsMerges,columnsKey,styles,fileName,ext,allValues} param
 * 自定义表头和sql数据导出（表头合并表格，数据不合并表格）
 * sqlKey : 数据sql编码
 * columnsList
 * columnsMerges
 * columnsKey
 * styles : 导出excl样式
 * fileName : 导出文件名
 * ext : 导出后缀 目前xecl、dbf
 * url : 接口地址
 */
export function getCustomSqlKeyRealize({
	sqlKey,
	columnsList,
	columnsMerges,
	columnsKey,
	styles,
	fileName = '导出文件',
	ext = 'xlsx',
	allValues = JSON.stringify({}),
}) {
	let content = {
		sheets: [
			{
				name: fileName,
				cells: columnsList,
				merges: columnsMerges,
				sqlKey: sqlKey, //sql编码
				sqlKeyHeader: columnsKey, //sql对应key对应列
			},
		],
		styles: exportStyles,
	};
	if (styles) {
		content.styles = styles;
	}
	try {
		let getFileData = giveFilePostDataInfoForTrue(
			{
				content: JSON.stringify(content),
				title: fileName,
				allValues: allValues,
			},
			`${apiUrl + '/DataObjApi/exportCustom'}`,
		);
		let token = getToken();
		downloadFile(
			getFileData.url,
			{
				...getFileData.datas,
				token: token,
			},
			fileName,
			ext,
		);
	} catch (err) {
		console.table('getCustomSqlKeyRealize', err);
	}
}

/**
 *
 * @param {data,columns,styles,defect,fileName,ext,url,eliminateRow,eliminateCol} param
 * 表头和数据导出（合并表格）
 * data : ant基础数据
 * columns : ant表头基础数据
 * styles : 导出excl样式
 * defect : 为null时默认数据
 * fileName : 导出文件名
 * ext : 导出后缀 目前xecl、dbf
 * url : 接口地址
 * eliminateRow : 列需要忽略合并的数据
 * eliminateCol : 行需要忽略合并的数据
 *
 */
export function getColumnsDataRealize({
	data = [],
	mergeKey = [],
	columns,
	styles,
	defect = null,
	fileName = '导出文件',
	ext = 'xlsx',
	eliminateRow = [],
	eliminateCol = [],
	mergeMappingRow = {}, // *映射mergeKey 纵向合并结果，key必须在mergeKey数组里面
	mergePrimaryRow, // 所有合并都会在当前mergePrimary 的范围下合并
}) {
	let content = getColumnsData({
		data,
		mergeKey,
		columns,
		styles,
		defect,
		fileName,
		ext,
		eliminateRow,
		eliminateCol,
		mergeMappingRow, // *映射mergeKey 纵向合并结果，key必须在mergeKey数组里面
		mergePrimaryRow, // 所有合并都会在当前mergePrimary 的范围下合并
	});
	if (styles) {
		content.styles = styles;
	}

	try {
		let getFileData = giveFilePostDataInfoForTrue(
			{
				content: JSON.stringify(content),
				title: fileName,
			},
			`${apiUrl + '/DataObjApi/exportCustom'}`,
		);
		let token = getToken();
		downloadFile(
			getFileData.url,
			{
				...getFileData.datas,
				token: token,
			},
			fileName,
			ext,
		);
	} catch (err) {
		console.table('getColumnsDataRealize', err);
	}
}

/**
 *
 * @param {data,columns,styles,defect,fileName,ext,url,eliminateRow,eliminateCol} param
 * 表头和数据导出（合并表格）
 * data : ant基础数据
 * columns : ant表头基础数据
 * styles : 导出excl样式
 * defect : 为null时默认数据
 * fileName : 导出文件名
 * ext : 导出后缀 目前xecl、dbf
 * url : 接口地址
 * eliminateRow : 列需要忽略合并的数据
 * eliminateCol : 行需要忽略合并的数据
 *
 */
export function getCustomDataRealize({
	data = [],
	mergeKey = [],
	columnsList = [],
	columnsMerges = [],
	columnsKey = [],
	bottomList = [],
	bottomMerges = [],
	styles,
	defect = null,
	fileName = '导出文件',
	ext = 'xlsx',
	eliminateRow = [],
	eliminateCol = [],
}) {
	let content = getCustomData({
		data,
		mergeKey,
		columnsList,
		columnsMerges,
		columnsKey,
		bottomList,
		bottomMerges,
		styles,
		defect,
		fileName,
		ext,
		eliminateRow,
		eliminateCol,
	});
	if (styles) {
		content.styles = styles;
	}

	try {
		let getFileData = giveFilePostDataInfoForTrue(
			{
				content: JSON.stringify(content),
				title: fileName,
			},
			`${apiUrl + '/DataObjApi/exportCustom'}`,
		);
		let token = getToken();
		downloadFile(
			getFileData.url,
			{
				...getFileData.datas,
				token: token,
			},
			fileName,
			ext,
		);
	} catch (err) {
		console.table('getCustomDataRealize', err);
	}
}
/**
 *
 * @param {data,columns,styles,defect,fileName,ext,url,eliminateRow,eliminateCol} param
 * 表头和数据导出（合并表格）
 * data : ant基础数据
 * columns : ant表头基础数据
 * styles : 导出excl样式
 * defect : 为null时默认数据
 * fileName : 导出文件名
 * ext : 导出后缀 目前xecl、dbf
 * url : 接口地址
 * eliminateRow : 列需要忽略合并的数据
 * eliminateCol : 行需要忽略合并的数据
 * mergeMappingRow : *映射mergeKey 纵向合并结果，key必须在mergeKey数组里面，value不可以在mergeKey里。
 * mergePrimary : 所有合并都会在当前mergePrimary 的范围下合并
 *
 */
export function getColumnsData({
	data = [],
	mergeKey = [],
	columns,
	styles,
	defect = null,
	fileName = '导出文件',
	ext = 'xlsx',
	eliminateRow = [],
	eliminateCol = [],
	docxSheet = {},
	mergeMappingRow = {}, // *映射mergeKey 纵向合并结果，key必须在mergeKey数组里面
	mergePrimaryRow, // 所有合并都会在当前mergePrimary 的范围下合并
}) {
	columns = deepCopy(columns);
	data = deepCopy(data);
	let { columnsList, columnsMerges, columnsKey, columnsHeight } = getColumns(columns);
	let { colSpanData, rowSpanData } = getSpanJson({
		mergeKey,
		data,
		eliminateRow,
		eliminateCol,
		mergeMappingRow,
		mergePrimaryRow,
	});
	// 处理数据
	let bodyData = [];
	let dataMerges = [];
	try {
		data.forEach((dv, di) => {
			let nowArroy = new Array(columnsKey.length).fill({});
			columnsKey.forEach((av, ai) => {
				nowArroy[ai] = {
					...uj,
					v: av in dv && dv[av] != null ? dv[av].toString() : defect || '',
				};
			});
			bodyData.push(nowArroy);
		});
		// 处理合并数据
		let newMergeKey = mergeKey;
		try {
			const newMergeMappingRow = Object.keys(mergeMappingRow).filter((item1) =>
				mergeKey.some((item2) => item2 === item1),
			);
			newMergeMappingRow.map((item) => {
				const mappingList = mergeMappingRow[item].filter(
					(item1) => !mergeKey.some((item2) => item2 === item1),
				);
				newMergeKey = [...newMergeKey, ...mappingList];
			});
		} catch (e) {
			console.table('newMergeKey', e);
		}
		Object.keys(rowSpanData).forEach((mv) => {
			rowSpanData[mv].forEach((cv, ci) => {
				if (cv > 1) {
					//合并表格的 开始行、结束行、开始列、结束列
					let rowIndex = columnsKey.indexOf(mv);
					dataMerges.push([columnsHeight + ci, columnsHeight + ci + cv - 1, rowIndex, rowIndex]);
				}
			});
		});
		Object.keys(colSpanData).forEach((mv) => {
			colSpanData[mv].forEach((cv, ci) => {
				if (cv > 1) {
					//合并表格的 开始行、结束行、开始列、结束列
					let rowIndex = columnsKey.indexOf(mv);
					dataMerges.push([columnsHeight + ci, columnsHeight + ci, rowIndex, rowIndex + cv - 1]);
				}
			});
		});
	} catch (err) {
		console.table('getColumnsData', err);
	}
	let content = {
		sheets: [
			{
				name: fileName,
				cells: [...columnsList, ...bodyData],
				merges: [...columnsMerges, ...dataMerges],
			},
		],
		styles: exportStyles,
	};
	if (ext === 'docx') {
		content.sheets[0] = {
			...content.sheets[0],
			...docxSheet,
		};
	}
	if (styles) {
		content.styles = styles;
	}
	return content;
}

/**
 *
 * @param {data,columns,styles,defect,fileName,ext,url,eliminateRow,eliminateCol} param
 * 表头和数据导出（合并表格）
 * data : ant基础数据
 * columns : ant表头基础数据
 * styles : 导出excl样式
 * defect : 为null时默认数据
 * fileName : 导出文件名
 * ext : 导出后缀 目前xecl、dbf
 * url : 接口地址
 * eliminateRow : 列需要忽略合并的数据
 * eliminateCol : 行需要忽略合并的数据
 *
 */
export function getCustomData({
	data = [],
	mergeKey = [],
	columnsList = [],
	columnsMerges = [],
	columnsKey = [],
	bottomList = [],
	bottomMerges = [],
	styles,
	defect = null,
	fileName = '导出文件',
	ext = 'xlsx',
	eliminateRow = [],
	eliminateCol = [],
	docxSheet = {},
}) {
	data = deepCopy(data);
	let columnsHeight = columnsList.length;
	let { colSpanData, rowSpanData } = getSpanJson({
		mergeKey,
		data,
		eliminateRow,
		eliminateCol,
	});
	// 处理数据
	let bodyData = [];
	let dataMerges = [];
	try {
		data.forEach((dv, di) => {
			let nowArroy = new Array(columnsKey.length).fill({});
			columnsKey.forEach((av, ai) => {
				nowArroy[ai] = {
					...uj,
					v: av in dv && dv[av] != null ? dv[av].toString() : defect || '',
				};
			});
			bodyData.push(nowArroy);
		});
		// 处理合并数据
		mergeKey.forEach((mv, mi) => {
			rowSpanData[mv].forEach((cv, ci) => {
				if (cv > 1) {
					//合并表格的 开始行、结束行、开始列、结束列
					let rowIndex = columnsKey.indexOf(mv);
					dataMerges.push([columnsHeight + ci, columnsHeight + ci + cv - 1, rowIndex, rowIndex]);
				}
			});
			colSpanData[mv].forEach((cv, ci) => {
				if (cv > 1) {
					//合并表格的 开始行、结束行、开始列、结束列
					let rowIndex = columnsKey.indexOf(mv);
					dataMerges.push([columnsHeight + ci, columnsHeight + ci, rowIndex, rowIndex + cv - 1]);
				}
			});
		});
	} catch (err) {
		console.table('getCustomData', err);
	}

	const columnsDataCells = [...columnsList, ...bodyData];
	const columnsDataMerges = [...columnsMerges, ...dataMerges];
	let newBottomMerges = [];
	if (bottomList && bottomList.length > 0) {
		// 新增底部数据
		if (columnsKey.length != bottomList[0].length) {
			console.table('bottomList数据列数和表头列数不一致');
			return;
		}
		newBottomMerges = bottomMerges.map((v, i) => {
			let newV = v;
			//合并表格的 开始行、结束行、开始列、结束列
			newV[0] += columnsDataCells.length;
			newV[1] += columnsDataCells.length;
			return v;
		});
	}

	let content = {
		sheets: [
			{
				name: fileName,
				cells: [...columnsDataCells, ...bottomList],
				merges: [...columnsDataMerges, ...newBottomMerges],
			},
		],
		styles: exportStyles,
	};
	if (ext === 'docx') {
		content.sheets[0] = {
			...content.sheets[0],
			...docxSheet,
		};
	}
	if (styles) {
		content.styles = styles;
	}
	return content;
}
// ant列表组件合并表格 render属性，合并纵向、横向。
export function renderContentAll(value, row, index, key, spanData, cloumnNames = []) {
	let colSpan,
		rowSpan = null;
	try {
		colSpan = spanData.colSpanData[key][index]; // 横向合并
		rowSpan = spanData.rowSpanData[key][index]; // 纵向合并
	} catch (err) {
		console.table('renderContentAll', err);
	}
	const obj = {
		children: value,
		props: {
			rowSpan: rowSpan,
			colSpan: colSpan,
		},
	};
	return obj;
}

// ant列表组件合并表格 render属性，合并纵向。 meanwhileKey :key 是本身字段key，value 是同步的字段key
export function renderContentRow(
	value,
	row,
	index,
	key,
	spanData,
	cloumnNames = [],
	meanwhileKey = {},
) {
	let colSpan,
		rowSpan = null;
	try {
		if (cloumnNames.indexOf(key) !== -1) {
			rowSpan = spanData.rowSpanData[key][index]; // 纵向合并
		} else {
			if (key in meanwhileKey && meanwhileKey[key]) {
				let meanwhileKeyValue = meanwhileKey[key];
				rowSpan = spanData.rowSpanData[meanwhileKeyValue][index]; // 同步字段 的纵向合并
			} else {
				rowSpan = 1;
			}
		}
	} catch (err) {
		console.table('renderContentRow', err);
	}
	const obj = {
		children: value,
		props: {
			rowSpan: rowSpan,
			colSpan: 1,
		},
	};
	return obj;
}

/**
 * 表头和数据导出（合并表格）
 * templatePath : word文档模板地址
 * params : word文档的替换参数
 * title : 导出文件名
 * allValues : sql参数
 * listConfig : 导出列表配置
 * ext : 导出后缀 目前xecl、dbf,docx,pdf
 * 返回值
 * */
export function getWord({
	templatePath,
	params,
	title,
	allValues = {},
	listConfig = {},
	ext = 'docx',
}) {
	try {
		let getFileData = giveFilePostDataInfoForTrue(
			{
				templatePath: templatePath,
				params: JSON.stringify({
					...listConfig,
					...setObjectKey(params),
				}),
				title: `${title}.${ext}`,
				allValues: JSON.stringify({ ...allValues }),
			},
			apiUrl + `/DataColumnApi/exportWord`,
		);
		let token = getToken();

		downloadFile(
			getFileData.url,
			{
				...getFileData.datas,
				token: token,
			},
			title,
			ext,
		);
	} catch (err) {
		console.table(err);
	}
}

/**
 * 表头和数据导出（合并表格）
 * templatePath : word文档模板地址
 * params : word文档的替换参数
 * title : 导出文件名
 * allValues : sql参数
 * listConfig : 导出列表配置
 * ext : 导出后缀 目前xecl、dbf,docx,pdf
 * 返回值
 * */
export function getFileAndShow({
	templatePath,
	params,
	title,
	allValues = {},
	listConfig = {},
	ext = 'docx',
}) {
	try {
		let getFileData = giveFilePostDataInfoForTrue(
			{
				templatePath: templatePath,
				params: JSON.stringify({
					...listConfig,
					...setObjectKey(params),
				}),
				title: `${title}.${ext}`,
				allValues: JSON.stringify({ ...allValues }),
			},
			apiUrl + `/DataColumnApi/exportWord`,
		);
		let token = getToken();
		downloadFileAndShowModal(
			getFileData.url,
			{
				...getFileData.datas,
				token: token,
			},
			title,
			ext,
		);
	} catch (err) {
		console.table(err);
	}
}

/**
 * 表头和数据导出（合并表格）
 * templatePath : word文档模板地址
 * params : word文档的替换参数
 * title : 导出文件名
 * allValues : sql参数
 * listConfig : 导出列表配置
 * ext : 导出后缀 目前xecl、dbf,docx,pdf
 * 返回值
 * */

export function getListWord({
	templatePath,
	paramsList = [],
	title,
	sonTitleKey,
	allValuesKey = [],
	listConfig = {},
	ext = 'zip',
	sonExt = 'pdf',
	filesKey = [],
}) {
	try {
		let content = [];
		paramsList.forEach((v, i) => {
			let files = [];
			let paramsObj = deepCopy(v);
			for (var ki in filesKey) {
				let files_ = v[filesKey[ki]];
				try {
					files = [...files, ...JSON.parse(files_).files];
				} catch (e) {}
				delete paramsObj[filesKey[ki]];
			}
			content.push({
				params: {
					...setObjectKey(paramsObj),
					...listConfig,
				},
				allValues: {
					...getObjectsKey(allValuesKey, paramsObj),
				},
				title: (paramsObj[sonTitleKey] || '未设置名称') + `.${sonExt}`,
				files: JSON.stringify(files),
			});
		});
		let getFileData = giveFilePostDataInfoForTrue(
			{
				templatePath: templatePath,
				content: JSON.stringify(content),
				zipTitle: `${title}.${ext}`,
			},
			apiUrl + `/DataColumnApi/batchExportWord`,
		);

		let token = getToken();
		downloadFile(
			getFileData.url,
			{
				...getFileData.datas,
				token: token,
			},
			title,
			ext,
		);
	} catch (err) {
		console.table(err);
	}
	function getObjectsKey(listKey = [], params = {}) {
		return listKey.filter((key) => Object.keys(params).indexOf(key)).reduce(
			(acc, key) => ({
				...acc,
				[key]: params[key] === null ? '' : params[key],
			}),
			{},
		);
	}
}

export function setObjectKey(data) {
	return Object.keys(data).reduce(
		(acc, key) => ({
			...acc,
			['${' + key + '}']: data[key] === null ? '' : data[key],
		}),
		{},
	);
}

/**
 * 修改对象key
 * 支持对象、数组对象
 * @param {*} obj 数组对象或者对象
 * @param {*} setKey {"被修改的key":"修改后的key"}
 * @returns
 */
export function upObjKey(obj, setKey = {}, defaultValue = '') {
	try {
		obj = deepCopy(obj);
		setKey = deepCopy(setKey);
		let objType = Object.prototype.toString.call(obj);
		if (
			obj &&
			(objType.indexOf('Array') > -1 || objType.indexOf('Object') > -1) &&
			Object.keys(setKey).length > 0
		) {
			let nowObj = null;
			if (objType === '[object Object]' && !Array.isArray(obj) && Object.keys(obj).length > 0) {
				nowObj = deepCopy(obj);
				for (var e in setKey) {
					let upKey = setKey[e];
					let { newKey = e, type, timeFormat } = getSetKeyValue(upKey);
					nowObj = {
						...nowObj,
						...getSetKeyJson({
							obj,
							e,
							newKey,
							type,
							timeFormat,
							defaultValue,
						}),
					};
					if (e != newKey) {
						delete nowObj[e];
					}
				}
			}
			if (objType === '[object Array]' && Array.isArray(obj) && obj.length > 0) {
				nowObj = new Array();
				obj.forEach((v, i, arr) => {
					let newJson = deepCopy(v);
					for (var e in setKey) {
						let upKey = setKey[e];
						let { newKey = e, type, timeFormat } = getSetKeyValue(upKey);
						newJson = {
							...newJson,
							...getSetKeyJson({
								obj: v,
								e,
								newKey,
								type,
								timeFormat,
								defaultValue,
							}),
						};
						if (e != newKey) {
							delete newJson[e];
						}
					}
					nowObj.push(newJson);
				});
			}
			return nowObj;
		} else {
			return null;
		}
	} catch (error) {
		console.table('upObjKey', error);
		return undefined;
	}
}

function getSetKeyValue(value) {
	let valeuType = Object.prototype.toString.call(value);
	let newName = null;
	let extendJson = {
		type: 'string',
	};
	if (valeuType === '[object String]') {
		newName = value;
	}
	if (valeuType === '[object Object]') {
		newName = value['new'];
		delete value['new'];
		extendJson = {
			...extendJson,
			...value,
		};
	}
	return {
		newKey: newName,
		...extendJson,
	};
}

function getSetKeyJson({ obj, e, newKey, type, timeFormat = 'YYYY-MM-DD HH:mm:ss', defaultValue }) {
	obj = deepCopy(obj);
	let value = obj[e];
	let newKeyObj = {};
	// delete obj[e];
	switch (type) {
		case 'time':
			newKeyObj[newKey] =
				(timeFormat && value ? moment(value).format(timeFormat) : value) || defaultValue;
			break;
		case 'flow':
			newKeyObj[newKey] = {
				code: value || defaultValue,
				type: 'flow',
			};
			break;
		default:
			newKeyObj[newKey] = value || defaultValue;
	}
	return newKeyObj;
}

// 下载附件FormdataWrapper
function isObject(value) {
	return value === Object(value);
}

function isArray(value) {
	return Array.isArray(value);
}

function isFile(value) {
	return value instanceof File;
}

function makeArrayKey(key) {
	return key;
}

export function FormdataWrapper(obj, fd, pre) {
	fd = fd || new FormData();
	Object.keys(obj).forEach(function(prop) {
		var key = pre ? pre + '[' + prop + ']' : prop;
		if (isObject(obj[prop]) && !isArray(obj[prop]) && !isFile(obj[prop])) {
			FormdataWrapper(obj[prop], fd, key);
		} else if (isArray(obj[prop])) {
			obj[prop].forEach(function(value) {
				var arrayKey = makeArrayKey(key);
				if (isObject(value) && !isFile(value)) {
					FormdataWrapper(value, fd, arrayKey);
				} else {
					fd.append(arrayKey, value);
				}
			});
		} else {
			if (obj[prop] != null) fd.append(key, obj[prop]);
		}
	});
	return fd;
}

// TODO http://scjoyedu.eicp.net:57400/zentao/task-view-4023.html  等生产环境更新后测试.
// http://xg.qnzy.net:51352/zyd/#/xg/student_affairs/MI/UrbanAndRuralMedicalInsurance/InsuredPersonnel
export async function downloadFile(url, params, fileName = '导出文件', ext = 'xlsx') {
	const { transformApi, headersApi } = await getTransformApi(url);
	let headers = getSassApiHeader();
	// if(headersApi){
	//   headers.apis = headersApi;
	// }
	fetch(transformApi, {
		method: 'POST',
		body: FormdataWrapper(params),
		headers,
	})
		.then(async (res) => {
			if (res.status + '' !== '200' || params.hasAsync) {
				return res.json();
			} else {
				return res.blob();
			}
		})
		.then((data) => {
			if (data && typeof data === 'object' && data.cacheKey) {
				showDownloadProgressFromCacheKey(data.cacheKey, { ext, fileName });
			} else if (data instanceof Blob) {
				let a = document.createElement('a');
				let url = window.URL.createObjectURL(data);
				let filename = fileName + '.' + ext;
				a.href = url;
				a.download = filename;
				a.target = '_blank';
				a.click();
				window.URL.revokeObjectURL(url);
				a = null;
			}
		})
		.catch((err) => {
			console.table(err);
		})
		.finally(() => {
			return true;
		});
}

export async function downloadFileAndShowModal(url, params, fileName = '导出文件', ext = 'xlsx') {
	const { transformApi, headersApi } = await getTransformApi(url);
	let headers = getSassApiHeader();
	// if(headersApi){
	//   headers.apis = headersApi;
	// }
	fetch(transformApi, {
		method: 'POST',
		body: FormdataWrapper(params),
		headers,
	})
		.then((res) => {
			if (res.status + '' !== '200') {
				return res.json();
			} else {
				return res.blob();
			}
		})
		.then((data) => {
			if (data instanceof Blob) {
				let url = window.URL.createObjectURL(data);
				let filename = fileName + '.' + ext;
				/**
         * 微软word 文档在线预览
         https://view.officeapps.live.com/op/view.aspx?src=
         https%3A%2F%2Fwww.longchang.gov.cn%2Flcs%2Fgsgg%2F202207%2F3ae45ccac65d40d885f40ec385ae287a%2Ffiles%2F%25E9%259A%2586%25E6%2598%258C%25E5%25B8%2582%25E7%25AC%25AC%25E5%2585%25AB%25E4%25B8%25AD%25E5%25AD%25A6%25E5%258E%2595%25E6%2589%2580%25E6%2594%25B9%25E9%2580%25A0%25E9%25A1%25B9%25E7%259B%25AE%25E5%2585%25AC%25E5%2591%258A.doc&wdOrigin=BROWSELINK
         * */
				Modal.info({
					title: filename,
					width: 1000,
					content: (
						<div>
							<embed
								width="100%"
								height="568px"
								name="plugin"
								id="pdfView"
								src={url}
								type="application/pdf"
								internalinstanceid="3"
								title={filename}
							/>
						</div>
					),
					okText: '确定',
					onCancel: () => {
						window.URL.revokeObjectURL(url);
					},
					onOk: () => {
						window.URL.revokeObjectURL(url);
					},
				});
			} else {
			}
		})
		.catch((err) => {
			console.table(err);
		})
		.finally(() => {
			return true;
		});
}
