import { defineComponent, type PropType, ref } from 'vue';
import { useCrud, useForm } from '@cool-vue/crud';
import { ElMessage } from 'element-plus';
import dayjs from 'dayjs';
import { isEmpty, orderBy } from 'lodash-es';
import { export_json_to_excel } from '../utils';
import { deepFind } from '/$/dict/utils';
import { useI18n } from 'vue-i18n';

export default defineComponent({
	name: 'cl-export-btn',

	props: {
		filename: [Function, String],
		autoWidth: {
			type: Boolean,
			default: true
		},
		bookType: {
			type: String,
			default: 'xlsx'
		},
		header: Array,
		columns: {
			type: Array as PropType<ClTable.Column[]>
		},
		data: [Function, Array],
		maxExportLimit: Number // 最大导出条数，不传或者小于等于0为不限制
	},

	setup(props, { slots }) {
		const { t } = useI18n();

		// crud
		const Crud = useCrud();

		// 表单
		const Form = useForm();

		// 加载状态
		const loading = ref(false);

		// 获取表头数据
		async function getHeader(columns: any[], fields: any[]) {
			return columns.filter(e => !e.hidden && fields.includes(e.prop)).map(e => e.label);
		}

		// 获取表格数据
		async function getData(): Promise<any[]> {
			const params = {
				...Crud.value?.paramsReplace(Crud.value.params),
				maxExportLimit: props.maxExportLimit,
				isExport: true
			};

			if (typeof props.data === 'function') {
				return props.data(params);
			} else {
				if (props.data) {
					return props.data;
				} else {
					if (Crud.value?.service) {
						return Crud.value?.service
							.page(params)
							.then(res => {
								return res.list.map((e, i) => {
									for (const k in e) {
										const col = props.columns?.find(c => c.prop == k);

										if (col) {
											// 格式化
											if (col.formatter) {
												e[k] = col.formatter(e, col, e[k], i);
											}

											// 字典
											if (col.dict) {
												e[k] =
													deepFind(e[k], col.dict as any)?.label || e[k];
											}
										}
									}

									return e;
								});
							})
							.catch(err => {
								ElMessage.error(err.message);
								return [];
							});
					} else {
						console.error('[cl-crud] Service is required');
						return [];
					}
				}
			}
		}

		// 获取文件名
		async function getFileName() {
			if (typeof props.filename === 'function') {
				return await props?.filename();
			} else {
				return props.filename || `Doc（${dayjs().format('YYYY-MM-DD HH_mm_ss')}）`;
			}
		}

		// 导出
		async function toExport(columns: ClTable.Column[]) {
			// 加载
			loading.value = true;

			// 字段
			const fields = columns.map(e => e.prop).filter(Boolean);

			// 表头
			const header = await getHeader(columns, fields);

			// 数据
			let data = await getData();

			if (!data) {
				loading.value = false;
				return ElMessage.error(t('导出数据异常'));
			}

			// 文件名
			const filename = await getFileName();

			// 过滤
			data = data.map(d => fields.map(f => d[f]));

			// 导出 excel
			export_json_to_excel({
				header,
				data,
				filename,
				autoWidth: props.autoWidth,
				bookType: props.bookType
			});

			loading.value = false;
		}

		function open() {
			if (!props.columns) {
				return console.error('[cl-export-btn] Columns is required');
			}

			// 表格列
			const columns = orderBy(props.columns, 'orderNum', 'asc').filter(
				e =>
					!(
						e.hidden === true ||
						['selection', 'expand', 'index', 'op'].includes(e.type) ||
						e.filterExport ||
						e['filter-export']
					)
			);

			Form.value?.open({
				title: t('导出'),
				width: '600px',
				props: {
					labelPosition: 'top'
				},
				form: {
					checked: columns.map(e => e.prop)
				},
				items: [
					{
						label: t('选择列'),
						prop: 'checked',
						component: {
							name: 'el-checkbox-group',
							options: columns.map(e => {
								return {
									label: String(e.label),
									value: e.prop
								};
							})
						}
					}
				],
				on: {
					submit(data, { close, done }) {
						if (isEmpty(data.checked)) {
							ElMessage.warning(t('请先选择要导出的列'));
							done();
						} else {
							toExport(columns.filter(e => data.checked.includes(e.prop)));
							close();
						}
					}
				}
			});
		}

		return () => {
			return (
				<el-button loading={loading.value} onClick={open}>
					{slots.default ? slots.default() : t('导出')}

					<cl-form ref={Form} />
				</el-button>
			);
		};
	}
});
