import { useCrud } from '@cool-vue/crud';
import { deepTree } from '/@/cool/utils';
import { isEmpty } from 'lodash-es';

interface Item extends Eps.BaseSysMenuEntity {
	children?: Item[];
	_children?: Item[];
	hasChildren?: boolean;
}

/**
 * 树形表格
 * @param options.lazy 是否懒加载，数据过多时开启
 * @param options.onRefresh 刷新方法
 * @returns
 */
export function toTree(
	options: { lazy?: boolean; onRefresh?: (params: any) => Promise<any[]> } = {}
) {
	return ({ exposed }) => {
		const Crud = useCrud();

		// 设置刷新方法
		if (Crud.value) {
			// 原 cl-crud 的 onRefresh
			const onRefresh = Crud.value.config.onRefresh;

			// 重写 onRefresh
			Crud.value.config.onRefresh = async (
				params: Parameters<ClCrud.Config['onRefresh']>[0],
				{ render, next, done }: Parameters<ClCrud.Config['onRefresh']>[1]
			) => {
				const req: Promise<any[]> = new Promise(resolve => {
					if (onRefresh) {
						const _next = async (params?: any) => {
							const res = await next(params);
							resolve(res.list);
						};

						const _render = (list: any[]) => {
							resolve(list);
						};

						onRefresh(params, { render: _render, next: _next, done });
					} else {
						resolve(
							options.onRefresh
								? options.onRefresh(params)
								: Crud.value?.service[Crud.value.dict.api.list](params)
						);
					}
				});

				const list = await req;

				render(onData(list, params.sort));
			};
		}

		// 数据处理
		const onData = (list: Item[], sort: 'desc' | 'asc') => {
			const data = deepTree(list, sort);

			// 递归处理
			const deep = (arr: Item[]) => {
				arr.forEach(e => {
					const nodes: { [key: number]: Item[] } =
						exposed.Table.value?.store.states.lazyTreeNodeMap.value || {};

					if (nodes[e.id!]) {
						nodes[e.id!] = e.children || [];
					}

					if (!isEmpty(e.children)) {
						e.hasChildren = true;
						e._children = e.children;

						if (options.lazy) {
							delete e.children;
						}

						deep(e._children || []);
					}
				});
			};

			deep(data);

			return data;
		};

		// 层级参数
		exposed.config.props.lazy = true;
		exposed.config.props['row-key'] = 'id';
		exposed.config.props['tree-props'] = {
			children: 'children',
			hasChildren: 'hasChildren'
		};

		// 层级事件
		exposed.config.on.load = (
			row: Item,
			treeNode: unknown,
			resolve: (data: Item[]) => void
		) => {
			resolve(row._children || []);
		};

		// 行点击
		exposed.config.on.onRowClick = (row: Item) => {
			if (row._children) {
				exposed.Table.value?.store.loadOrToggle(row);
			}
		};
	};
}
