import { CSSProperties } from 'vue';
import { MenuItemDef, DefaultMenuItem } from '../types/index';
export * from './GridCustomExportManager';
export type * from './GridCustomExportManager';

/**
 * 在AG Grid右下角前方插入文本
 * @param erFormHelper
 * @param grid id
 * @param template 模板：{type|field|formater}的格式。例：{count|MAT_NO}-统计MAT_NO的数量；{sum|SHEET_NUM|2}-统计SHEET_NUM的和并且保留2位小数；{fun|HEAT_TREAT_MODE|T}-自定义方法统计HEAT_TREAT_MODE字段并且传递参数T
 * @param opts.fontStyle 显示的字体样式，同CSS
 * @param opts.fun 自定义函数,当模板中type=fun时，会调用opts.fun方法；回调参数：字段名，行数据，格式化参数。返回值必须为数字！否则无效
 */
export function setGridStatusBar(
	erFormHelper: any,
	grid: string,
	template: string,
	opts?: {
		fontStyle?: CSSProperties;
		fun?: (field: string, row: { [key: string]: any }, format: string) => number;
	}
) {
	const bar_class_name = '--lxy-ag-grid-tj';
	const api = erFormHelper.getGridApi(grid);
	const bar_opts = erFormHelper.getGrid(grid).statusBar.statusPanels as any[];
	const panel_name = bar_opts.at(-1).statusPanel;
	const bar_instance = erFormHelper.getGridApi(grid)?.getStatusPanel(panel_name) as any;
	const bar_el = (bar_instance.$el || bar_instance.eGui) as HTMLElement;
	const outer_el = bar_el.parentElement?.parentElement;
	const child_el = bar_el.parentElement;
	let node = createNode(opts?.fontStyle);
	const has = outer_el?.querySelector(`.${bar_class_name}`);
	if (!has) {
		node.apply();
		// filter事件
		api?.addEventListener('filterChanged', (e: any) => {
			node.updataValue();
		});
		(window as any)['TJBAR'] = node;
	} else {
		(window as any)['TJBAR']?.updataValue?.();
	}
	// 创建Node
	function createNode(css?: CSSProperties) {
		const div = document.createElement('div');
		div.innerText = template;
		div.style.marginLeft = 'auto';
		div.style.display = 'flex';
		div.style.alignItems = 'center';
		div.classList.add(bar_class_name);
		for (const key in css) {
			(div.style as any)[key] = String(css[key as any]);
		}
		return {
			apply() {
				this.updataValue();
				outer_el?.insertBefore(div, child_el);
			},
			updataValue() {
				div.innerText = updateTemplate(template);
			},
			remove() {
				div.remove();
			},
		};
	}
	// 替换模板
	interface Rules {
		type: 'count' | 'sum' | 'fun';
		field: string;
		template: string;
		rule: string;
		format?: string;
		value: number;
	}
	function updateTemplate(template: string) {
		const regex = /(?<=\{)[^{}]+(?=\})/g;
		const res_match = template.match(regex);
		const rules: Rules[] = [];
		if (res_match?.length) {
			res_match.forEach((str, i) => {
				// 去掉全部空格
				const str_old = str;
				const rule = str.replace(/\s/g, '');
				const rule_type = rule.split('|')[0] as any;
				const rule_field = rule.split('|')[1];
				const rule_float = rule.split('|')[2];
				rules.push({
					type: rule_type,
					field: rule_field,
					template: str_old,
					rule,
					format: rule_float,
					value: 0,
				});
			});
		}
		api?.forEachNodeAfterFilterAndSort((node_row, i) => {
			const data_row = node_row.data.toJSON();
			for (let j = 0; j < rules.length; j++) {
				const item = rules[j];
				if (!Reflect.has(data_row, item.field)) {
					break;
				}
				if (item.type === 'sum') {
					item.value += Number(data_row[item.field]);
				}
				if (item.type === 'count') {
					item.value += data_row[item.field]?.toString() ? 1 : 0;
				}
				if (item.type === 'fun') {
					item.value += opts?.fun?.(item.field, data_row, item?.format ?? '') || 0;
				}
			}
		});
		rules.forEach((item) => {
			const float = Number.parseInt(item.format ?? '0');
			let value = item.value.toString();
			if (value.includes('.')) {
				value = Number(value).toFixed(float);
			}
			template = template.replace(`{${item.template}}`, value);
		});
		return template;
	}
}

/**
 * 导出多个ag grid数据为Excel
 * @param erFormHelper
 * @param name_file 导出之后的文件名，不包括后缀
 * @param opts.grid id
 * @param opts.name_sheet sheet名称，默认从Sheet1开始
 * @param opts.columns 需要导出的列，默认全部列
 * @param opts.formatter 单元格格式化函数，返回值必须为字符串！
 */
export function exportGridByMulSheet(
	erFormHelper: any,
	name_file: string,
	opts: {
		grid: string;
		name_sheet?: string;
		columns?: string[];
		formatter?: (params: { value: any; row: { [key: string]: any }; column: string }) => string;
	}[]
) {
	const data_export = opts.reduce((pre: string[], opt, i) => {
		const gridApi = erFormHelper.getGridApi(opt.grid);
		const { grid, name_sheet, columns, formatter } = opt;
		if (gridApi) {
			const _opt: { [key: string]: any } = {};
			if (name_sheet) {
				_opt['sheetName'] = name_sheet;
			} else {
				_opt['sheetName'] = `Sheet${i + 1}`;
			}
			if (columns) {
				_opt['columnKeys'] = columns;
			}
			if (formatter) {
				_opt['processCellCallback'] = (params: any) => {
					const { value, node, column } = params;
					const str = formatter.call(window, {
						value,
						row: node?.data,
						column: column.getColId(),
					});
					return str;
				};
			}
			const temp = gridApi.getSheetDataForExcel({
				..._opt,
			});
			if (temp) {
				pre.push(temp);
			} else {
				throw `[${grid} sheet data] is undefined.`;
			}
		} else {
			throw `[${grid}] is undefined.`;
		}
		return pre;
	}, []);
	const api = erFormHelper.getGridApi(opts[0].grid);
	api?.exportMultipleSheetsAsExcel({
		data: data_export,
		fileName: `${name_file}.xlsx`,
	});
}

/**
 * 获取grid配置的颜色
 * @param erFormHelper
 * @param grid id
 */
export function getGridColorConfig(erFormHelper: any, grid: string) {
	const res: { color: string; desc: string; field: string; mark: string; rule: string; target: string; _data: any[] }[] = [];
	const gridStyles = (erFormHelper.ConfigInfo.TSI00GRIDSTYLE.data as any[]).filter((item) => item.FUNCTION_ID === grid);
	gridStyles.map((row) => {
		const color = (row.FILL_COLOR as string).trim();
		const desc = (row.REMARK as string).trim();
		const field = (row.COL_NAME as string).trim();
		const mark = (row.CONST_PARA as string).trim();
		const rule = (row.REGULAR_EXPRESS as string).trim();
		const target = (row.FUNCTION_ID as string).trim();
		if (desc && !field.startsWith('_')) {
			res.push({ desc, color, field, mark, rule, target, _data: row });
		}
	});
	return res;
}

/**
 * 设置grid内容右键菜单,详情可查看官网：https://www.ag-grid.com/react-data-grid/context-menu/#built-in-menu-items
 * @param erFormHelper
 * @param grid id
 */
export function setGridContentMenu(erFormHelper: any, grid: any, menus: (e: any) => (MenuItemDef | DefaultMenuItem)[]) {
	let api = erFormHelper.getGridApi(grid);
	api?.setGetContextMenuItems((params: any) => {
		return menus.call(window, params);
	});
}

/**
 * 滚动grid到指定index行
 * @param erFormHelper
 * @param grid id
 * @param targetValue 目标对象，建议尽量为数据中的唯一值字段
 * @param opts.keepLine 保留行数，默认为5行
 * @param opts.reMerge 是否重新给grid设置数据
 * @returns
 */
export function scrollGridToData(erFormHelper: any, grid: any, targetValue: { [key: string]: any }, opts?: { keepLine?: number; reMerge?: boolean }) {
	const keepLine = opts?.keepLine ?? 5;
	const reMerge = opts?.reMerge ?? true;
	let gridData = erFormHelper.getGridRows(grid, 'all', true);
	let findIndex = gridData.findIndex((row: { [key: string]: any }, i: number) =>
		Object.keys(targetValue).every((key) => row[key] === targetValue[key])
	);
	if (findIndex <= -1) return;
	if (findIndex - keepLine > 0) {
		findIndex -= keepLine;
	}
	const api = erFormHelper.getGridApi(grid);
	if (reMerge) {
		erFormHelper.mergeDataToGrid(gridData, grid);
	}
	api?.ensureIndexVisible(findIndex, 'top');
	setTimeout(() => {
		erFormHelper.setGridIndicator(grid, { [Object.keys(targetValue)[0]]: Object.values(targetValue)[0] });
	}, 100);
}

/**
 * 滚动指定grid指定px
 * @param erFormHelper
 * @param grid id
 * @param px 滚动的像素
 */
export function scrollGridByPx(erFormHelper: any, grid: string, px: number) {
	const api = erFormHelper.getGridApi(grid);
	(api as any).gridBodyCtrl.scrollVertically(px);
}

/**
 * AG Grid 筛选管理
 * @constructor erFormHelper
 * @constructor grid id
 */
export class AgGirdFilterManger {
	private erFormHelper: any;
	private recordOn = false;
	private model_old = {};
	private api: any = null;
	constructor(erFormHelper: any, grid_id: string) {
		this.erFormHelper = erFormHelper;
		this.api = this.erFormHelper.getGridApi(grid_id);
		if (!this.api) {
			throw new Error(`[${grid_id} is not found]`);
		}
		// 添加 filterChanged 事件
		this.api.addEventListener('filterChanged', () => {
			if (this.recordOn) {
				this.model_old = this.api!.getFilterModel();
			}
		});
	}
	// 记录 用于需要保留当前筛选设置的情况
	record = {
		on: () => {
			this.recordOn = true;
		},
		off: (clearAll = false) => {
			this.recordOn = false;
			clearAll && (this.model_old = {});
		},
		set: () => {
			this.api?.setFilterModel(this.model_old);
		},
	};
	/**
	 * 设置列筛选
	 * @param filterOpts 对象格式：{列1英文名:筛选值1,列2英文名:筛选值2,列2英文名:筛选值2,...}
	 */
	filter(filterOpts: { [col_name: string]: string }) {
		Object.entries(filterOpts).forEach(([col_name, col_filter_value]) => {
			const col = this.api?.getColumnDef(col_name);
			if (col_name === col?.field) {
				this.api?.setFilterModel({
					[col_name]: {
						// 低代码列好像都用的 multi
						filterType: 'multi',
						filterModels: [
							{
								// 筛选类型
								filterType: 'text',
								// type: 筛选方式
								type: 'startWidths',
								// 筛选的值
								filter: col_filter_value,
							},
						],
					},
				});
			}
		});
	}
	/**
	 * 清除当前筛选设置
	 */
	clear() {
		this.api?.setFilterModel(null);
	}
}

/**
 * 获取Grid的Nodes数据
 * @param erFormHelper
 * @param grid id
 * @param toJson 是否转化为json数据
 */
export function getGridDataByNodes(erFormHelper: any, grid: string, toJson?: boolean) {
	const back: { [key: string]: any }[] = [];
	const api = erFormHelper.getGridApi(grid) as any;
	api.forEachNode((node: any, i: number) => {
		if (toJson) {
			back.push(node.data.toJSON());
		} else {
			back.push(node.data);
		}
	});
	return back;
}
