import {
	BizCalender,
	BizCreate,
	BizDestroy,
	BizDetail,
	BizDrag,
	BizEditor,
	BizImport,
	BizList,
	BizPage,
	BizProps,
	BizTourProps,
	BizTree,
	BizUpdate,
	BizValueType,
	DealerFormItem,
	DealerList,
	OrderFormItem,
	OrderList,
	PageContainer,
	Remark,
	RemarkFormItem,
	SmartActionBar,
	SupplierFarmerList,
	UserFormItem,
	UserList,
} from '@/components';
import { useIntl } from '@@/exports';
import { UserOutlined } from '@ant-design/icons';
import {
	ActionType,
	ParamsType,
	ProColumns,
	ProFormDependency,
	ProFormSwitch,
	ProFormTextArea,
	ProProvider,
	RouteContext,
	RouteContextType,
} from '@ant-design/pro-components';
import { Avatar, Button, message, Space, Switch, Tour, TourProps } from 'antd';
import { Dayjs } from 'dayjs';
import {
	useContext,
	useEffect,
	useImperativeHandle,
	useRef,
	useState,
} from 'react';

export default function BizContainer<
	Func extends Record<string, any>,
	BizVO extends Record<string, any>,
	BizPageQry extends Record<string, any>,
	BizCreateCmd extends Record<string, any> = ParamsType,
	BizUpdateCmd extends Record<string, any> = ParamsType,
>(props: BizProps<Func, BizVO, BizPageQry, BizCreateCmd, BizUpdateCmd>) {
	const {
		permission,
		func,
		method,
		methodUpper,
		intlPrefix,
		rowKey,

		onValueChange,
		remark = false,
		status = false,

		modeType,
		container,
		page = false,
		tree = false,
		drag = false,
		calender = false,
		create = false,
		update = false,
		destroy = false,
		detail = false,
		batchImport = false,
		list = false,
		tour = {},
	} = props;

	const common = {
		permission,
		func,
		method,
		methodUpper,
		intlPrefix,
		rowKey,
	};

	const intl = useIntl();

	const { ghost = false, fieldProps: containerProps } = container || {};

	const actionRef = useRef<ActionType>();

	// @ts-ignore
	useImperativeHandle(page?.fieldProps?.actionRef, () => actionRef.current, [
		actionRef.current,
	]);

	const [openTour, setOpenTour] = useState(false);
	const [currentStep, setCurrentStep] = useState(0);
	const [tourSteps, setTourSteps] = useState<TourProps['steps']>([]);

	const initTour = (tour: BizTourProps) => {
		// 定义引导步骤
		const steps: TourProps['steps'] = [
			...(tour.expandSteps && tour.expandSteps.length > 0
				? tour.expandSteps
				: []),
		];

		if (tour.steps) {
			setTourSteps([...steps, ...tour.steps]);
			return;
		}

		const bizFilter = document.querySelector('.ant-pro-query-filter');
		if (bizFilter) {
			steps.push({
				title: '查询表单',
				description: '在这里可以通过多个条件组合筛选表格数据',
				//@ts-ignore
				target: () => document.querySelector('.ant-pro-query-filter')!,
			});
		}

		const bizSearch = document.querySelector('.ant-btn-primary');

		if (bizSearch) {
			steps.push({
				title: '搜索按钮',
				description: '点击这里执行查询操作',
				//@ts-ignore
				target: () => document.querySelector('.ant-btn-primary')!,
				placement: 'left',
			});
		}

		const statistics = document.querySelector('.statistics');

		if (statistics) {
			steps.push({
				title: '数据统计',
				description: '这里会显示所有的数据的统计信息',
				//@ts-ignore
				target: () => document.querySelector('.statistics')!,
				placement: 'bottom',
			});
		}

		const bizCreate = document.querySelector(
			'.ant-pro-table-list-toolbar .ant-pro-table-list-toolbar-right .biz-create',
		);
		if (bizCreate) {
			steps.push({
				title: intl.formatMessage({
					id: intlPrefix + '.modal.create.button',
				}),
				description: '点击这里可以新建一条数据',
				//@ts-ignore
				target: () =>
					document.querySelector(
						'.ant-pro-table-list-toolbar .ant-pro-table-list-toolbar-right .biz-create',
					)!,
				placement: 'left',
			});
		}

		const bizImport = document.querySelector(
			'.ant-pro-table-list-toolbar .ant-pro-table-list-toolbar-right .biz-import',
		);
		if (bizImport) {
			steps.push({
				title: intl.formatMessage({
					id: intlPrefix + '.modal.import.button',
				}),
				description: '点击这里可以导入数据',
				//@ts-ignore
				target: () =>
					document.querySelector(
						'.ant-pro-table-list-toolbar .ant-pro-table-list-toolbar-right .biz-import',
					)!,
				placement: 'bottom',
			});
		}

		const bizCustomField = document.querySelector('.biz-custom-field');
		// 字段配置
		if (bizCustomField) {
			steps.push({
				title: '字段配置',
				description: '点击这里可以配置字段',
				//@ts-ignore
				target: () => document.querySelector('.biz-custom-field')!,
				placement: 'bottom',
			});
		}
		const proTableToolbarTab = document.querySelector(
			'.ant-pro-table-list-toolbar-left-has-tabs',
		);
		// tab
		if (proTableToolbarTab) {
			steps.push({
				title: '类型切换',
				description: '点击这里可以切换不同类型的数据',
				//@ts-ignore
				target: () =>
					document.querySelector('.ant-pro-table-list-toolbar-left-has-tabs')!,
				placement: 'bottom',
			});
		}

		const table = document.querySelector('.ant-table');
		if (table) {
			steps.push({
				title: '数据表格',
				description: '查询结果会显示在这里，点击表头可以排序',
				//@ts-ignore
				target: () => document.querySelector('.ant-table')!,
				placement: 'top',
			});
		}

		const calendar = document.querySelector('.ant-picker-calendar');
		if (calendar) {
			steps.push({
				title: '日历',
				description: '点击这里可以查看日历',
				//@ts-ignore
				target: () => document.querySelector('.ant-picker-calendar')!,
			});
		}

		let options = document.querySelector(
			'.ant-table-row:nth-child(2) .ant-table-cell:last-child',
		);
		if (options) {
			steps.push({
				title: '操作栏',
				description: '这里包含行编辑、删除等操作按钮',
				//@ts-ignore
				target: () =>
					document.querySelector(
						'.ant-table-row:nth-child(2) .ant-table-cell:last-child',
					)!,
			});
		}

		let pagination = document.querySelector('.ant-pagination');
		if (pagination) {
			steps.push({
				title: '分页器',
				description: '可以通过分页器查看更多数据',
				//@ts-ignore
				target: () => document.querySelector('.ant-pagination')!,
				placement: 'top',
			});
		}
		setTourSteps(steps);
	};

	useEffect(() => {
		if (tour) {
			initTour(tour);
		}
	}, []);

	const renderStatus = () => {
		if (!status) {
			return null;
		}
		return (
			<ProFormSwitch
				key={'status'}
				name={'status'}
				label={intl.formatMessage({
					id: intlPrefix + '.form.status.label',
				})}
				required={true}
				placeholder={intl.formatMessage({
					id: intlPrefix + '.form.status.placeholder',
				})}
				rules={[
					{
						required: true,
						message: intl.formatMessage({
							id: intlPrefix + '.form.status.required',
						}),
					},
				]}
				checkedChildren="启用"
				unCheckedChildren="禁用"
			/>
		);
	};

	const renderRemark = () => {
		if (remark && remark.mode === 'textarea') {
			return (
				<ProFormTextArea
					key={'remark'}
					label={intl.formatMessage({ id: intlPrefix + '.form.remark.label' })}
					name={'remark'}
					fieldProps={{
						autoSize: { minRows: 3, maxRows: 6 },
						showCount: true,
						maxLength: 200,
					}}
					placeholder={intl.formatMessage({
						id: intlPrefix + '.form.remark.placeholder',
					})}
				/>
			);
		}

		if (remark && remark.mode === 'editor') {
			return (
				<ProFormDependency key={'remark'} name={['remark']}>
					{({ remark }, form) => {
						return (
							<BizEditor
								key={'remark'}
								value={remark}
								onChange={(value) => {
									form.setFieldValue('remark', value);
								}}
								label={intl.formatMessage({
									id: intlPrefix + '.form.remark.label',
								})}
								name={'remark'}
								placeholder={intl.formatMessage({
									id: intlPrefix + '.form.remark.placeholder',
								})}
							/>
						);
					}}
				</ProFormDependency>
			);
		}
	};

	const renderCreate = (isMobile?: boolean) => {
		if (create) {
			const { display } = create;
			if (display && !display()) {
				return undefined;
			}
			if (modeType !== 'create') {
				delete create.trigger;
			}
			return (
				<BizCreate<BizVO, BizCreateCmd, Func>
					{...common}
					isMobile={isMobile}
					{...create}
					formContext={[create.formContext, renderStatus(), renderRemark()]}
					onFinish={async (record) => {
						await actionRef?.current?.reload();
						onValueChange?.();
						create?.onFinish?.(record);
					}}
				/>
			);
		}
	};

	const renderImport = (isMobile?: boolean) => {
		if (batchImport) {
			const { display } = batchImport;
			if (display && !display()) {
				return undefined;
			}
			if (modeType !== 'import') {
				delete batchImport.trigger;
			}
			return (
				<BizImport<BizVO, BizCreateCmd, Func>
					{...common}
					isMobile={isMobile}
					{...batchImport}
					onFinish={async () => {
						await actionRef?.current?.reload();
						onValueChange?.();
						batchImport?.onFinish?.();
					}}
				/>
			);
		}
	};

	const renderUpdate = (record?: BizVO, isMobile?: boolean) => {
		if (update) {
			const updateRowId = record?.[rowKey] || update?.rowId;
			const { display } = update;
			if (display && !display(record)) {
				return undefined;
			}
			if (modeType !== 'update') {
				delete update.trigger;
			}
			return (
				updateRowId && (
					<BizUpdate<BizVO, BizUpdateCmd, Func>
						positionKey="edit"
						key={'update'}
						row={record}
						{...common}
						isMobile={isMobile}
						{...update}
						formContext={[update.formContext, renderStatus(), renderRemark()]}
						rowId={updateRowId}
						onFinish={async (record) => {
							await actionRef?.current?.reload();
							onValueChange?.();
							update?.onFinish?.(record);
						}}
					/>
				)
			);
		}
	};

	const renderDestroy = (record?: BizVO, isMobile?: boolean) => {
		if (destroy) {
			const destroyRowId = record?.[rowKey] || destroy?.rowId;
			const { display } = destroy;
			if (display && !display(record)) {
				return undefined;
			}
			return (
				destroyRowId && (
					<BizDestroy<BizVO, Func>
						key={'destroy'}
						positionKey="delete"
						row={record}
						{...common}
						isMobile={isMobile}
						{...destroy}
						rowId={destroyRowId}
						onFinish={async () => {
							await actionRef?.current?.reload();
							onValueChange?.();
							destroy?.onFinish?.();
						}}
					/>
				)
			);
		}
	};

	const renderDetail = (record?: BizVO, isMobile?: boolean) => {
		if (detail) {
			const detailRowId = record?.[rowKey] || detail?.rowId;
			const { display } = detail;
			if (display && !display(record)) {
				return undefined;
			}
			if (modeType !== 'detail') {
				delete detail.trigger;
			}

			return (
				detailRowId && (
					<BizDetail<BizVO, Func>
						key={'detail'}
						positionKey="view"
						row={record}
						{...common}
						isMobile={isMobile}
						{...detail}
						//@ts-ignore
						columns={[
							...(detail?.columns || []),
							...(remark
								? [
										{
											title: intl.formatMessage({
												id: intlPrefix + '.column.remark',
											}),
											dataIndex: 'remark',
											valueType: 'remark',
											key: 'remark',
										},
									]
								: []),
						]}
						rowId={detailRowId}
						onFinish={async (record) => {
							await actionRef?.current?.reload();
							onValueChange?.();
							detail?.onFinish?.(record);
						}}
					/>
				)
			);
		}
	};

	const render = (isMobile?: boolean) => {
		if (modeType === 'create') {
			return renderCreate(isMobile);
		}

		if (modeType === 'destroy') {
			return renderDestroy(undefined, isMobile);
		}

		if (modeType === 'update') {
			return renderUpdate(undefined, isMobile);
		}

		if (modeType === 'detail') {
			return renderDetail(undefined, isMobile);
		}

		const expandColumns: ProColumns<BizVO, BizValueType>[] = [
			...((status
				? [
						{
							title: intl.formatMessage({ id: intlPrefix + '.column.status' }),
							dataIndex: 'status',
							key: 'status',
							valueType: 'select',
							fieldProps: {
								placeholder: intl.formatMessage({
									id: intlPrefix + '.column.status.placeholder',
								}),
							},
							valueEnum: {
								true: {
									text: intl.formatMessage({
										id: intlPrefix + '.column.status.enum.enabled',
									}),
									status: 'Success',
								},
								false: {
									text: intl.formatMessage({
										id: intlPrefix + '.column.status.enum.disabled',
									}),
									status: 'Error',
								},
							},
							renderText: (status: boolean, record: BizVO) => (
								<Switch
									checked={status}
									onChange={async (checked) => {
										const formData = {
											[rowKey]: record[rowKey],
											status: checked,
										};

										const { success } = await func?.[`update${methodUpper}`]?.(
											formData as any,
										);

										if (success) {
											message.success(
												intl.formatMessage({
													id: intlPrefix + '.modal.update.status.success',
												}),
											);
										}

										actionRef.current?.reload();
									}}
									checkedChildren={intl.formatMessage({
										id: intlPrefix + '.column.status.enum.enabled',
									})}
									unCheckedChildren={intl.formatMessage({
										id: intlPrefix + '.column.status.enum.disabled',
									})}
									className={status ? 'bg-green-500' : 'bg-gray-400'}
								/>
							),
						},
					]
				: []) as ProColumns<BizVO, BizValueType>[]),
			...((remark
				? [
						{
							title: intl.formatMessage({ id: intlPrefix + '.column.remark' }),
							dataIndex: 'remark',
							valueType: 'remark',
							key: 'remark',
						},
					]
				: []) as ProColumns<BizVO, BizValueType>[]),
			{
				title: intl.formatMessage({ id: intlPrefix + '.column.createdAt' }),
				dataIndex: 'createdAt',
				key: 'createdAt',
				search: false,
			},
			{
				title: intl.formatMessage({ id: intlPrefix + '.column.option' }),
				valueType: 'option',
				key: 'option',
				search: false,
				...(!isMobile
					? {
							fixed: 'right',
						}
					: {}),
				render: (_, record) => [
					<SmartActionBar
						key={'options'}
						isMobile={isMobile}
						maxVisibleItems={3}
						fixedPositions={['view', 'edit', 'delete']}
					>
						{modeType === 'page' && page && page.options?.(record, actionRef)}
						{modeType === 'tree' && tree && tree.options?.(record, actionRef)}
						{modeType === 'drag' && drag && drag.options?.(record, actionRef)}
						{modeType === 'list' && list && list.options?.(record, actionRef)}
						{renderDetail(record, isMobile)}
						{renderUpdate(record, isMobile)}
						{renderDestroy(record, isMobile)}
					</SmartActionBar>,
				],
			},
		];

		if (modeType === 'page' && page) {
			const { columns, fieldProps, ...rest } = page;

			return (
				<BizPage<BizVO, BizPageQry, Func>
					{...common}
					isMobile={isMobile}
					columns={[...columns, ...expandColumns]}
					fieldProps={{
						...fieldProps,
						actionRef: actionRef,
						toolBarRender: (action, rows) => [
							// @ts-ignore
							...(fieldProps?.toolBarRender?.(action, rows) || []),
							renderImport(isMobile),
							renderCreate(isMobile),
						],
					}}
					{...rest}
				/>
			);
		}

		if (modeType === 'tree' && tree) {
			const { columns, fieldProps, ...rest } = tree;

			return (
				<BizTree<BizVO, BizPageQry, Func>
					{...common}
					isMobile={isMobile}
					columns={[...columns, ...expandColumns]}
					fieldProps={{
						...fieldProps,
						actionRef: actionRef,
						toolBarRender: (action, rows) => [
							// @ts-ignore
							...(fieldProps?.toolBarRender?.(action, rows) || []),
							renderImport(isMobile),
							renderCreate(isMobile),
						],
					}}
					{...rest}
				/>
			);
		}

		if (modeType === 'drag' && drag) {
			const { columns, fieldProps, ...rest } = drag;

			return (
				<BizDrag<BizVO, BizPageQry, Func>
					{...common}
					isMobile={isMobile}
					columns={[...columns, ...expandColumns]}
					fieldProps={{
						...fieldProps,
						actionRef: actionRef,
						toolBarRender: (action, rows) => [
							// @ts-ignore
							...(fieldProps?.toolBarRender?.(action, rows) || []),
							renderImport(isMobile),
							renderCreate(isMobile),
						],
					}}
					{...rest}
				/>
			);
		}

		if (modeType === 'list' && list) {
			const { columns, metas, fieldProps, ...rest } = list;
			if (status) {
				metas.description = {
					dataIndex: 'status',
					render: (_, record: BizVO) => (
						<Switch
							checked={record.status}
							onChange={async (checked) => {
								const formData = {
									[rowKey]: record[rowKey],
									status: checked,
								};

								const { success } = await func?.[`update${methodUpper}`]?.(
									formData as any,
								);

								if (success) {
									message.success(
										intl.formatMessage({
											id: intlPrefix + '.modal.update.status.success',
										}),
									);
								}

								actionRef.current?.reload();
							}}
							checkedChildren={intl.formatMessage({
								id: intlPrefix + '.column.status.enum.enabled',
							})}
							unCheckedChildren={intl.formatMessage({
								id: intlPrefix + '.column.status.enum.disabled',
							})}
							className={status ? 'bg-green-500' : 'bg-gray-400'}
						/>
					),
				};
			}

			// @ts-ignore
			metas.extra = {
				// @ts-ignore
				render: (_, record: BizVO) => [
					<SmartActionBar
						key={'options'}
						isMobile={isMobile}
						maxVisibleItems={3}
						fixedPositions={['view', 'edit', 'delete']}
					>
						{modeType === 'list' && list && list.options?.(record, actionRef)}
						{renderDetail(record, isMobile)}
						{renderUpdate(record, isMobile)}
						{renderDestroy(record, isMobile)}
					</SmartActionBar>,
				],
			};

			return (
				<BizList<BizVO, BizPageQry, Func>
					{...common}
					isMobile={isMobile}
					columns={columns}
					metas={metas}
					fieldProps={{
						...fieldProps,
						actionRef: actionRef,
						toolBarRender: (action, rows) => [
							// @ts-ignore
							...(fieldProps?.toolBarRender?.(action, rows) || []),
							renderImport(isMobile),
							renderCreate(isMobile),
						],
					}}
					{...rest}
				/>
			);
		}

		if (modeType === 'calender' && calender) {
			const { fieldProps, ...rest } = calender;
			return (
				<BizCalender<BizVO, BizPageQry, Func>
					{...common}
					isMobile={isMobile}
					fieldProps={{
						...fieldProps,
						cardProps: {
							extra: (
								<Space>
									{renderImport(isMobile)}
									{renderCreate(isMobile)}
								</Space>
							),
						},
						actionRef: actionRef,
						detailRender: (record, value: Dayjs) => {
							return (
								(detail && (
									<BizDetail<BizVO, Func>
										row={record}
										{...common}
										{...detail}
										rowId={record?.[rowKey]}
										onFinish={async (record) => {
											await actionRef?.current?.reload();
											onValueChange?.();
											detail?.onFinish?.(record);
										}}
										trigger={(item?: BizVO) =>
											fieldProps?.detailRender?.(item!, value)
										}
									/>
								)) ||
								fieldProps?.detailRender?.(record!, value)
							);
						},
					}}
					{...rest}
				/>
			);
		}
	};

	const values = useContext(ProProvider);

	const renderContext = () => {
		return (
			<ProProvider.Provider
				value={{
					...values,
					valueTypeMap: {
						dealer: {
							renderFormItem: (_, props) => {
								return <DealerFormItem {...props} {...props?.fieldProps} />;
							},
							render: (dealerVO: BusinessAPI.DealerVO) => {
								console.log('dealerVO', dealerVO);
								return (
									dealerVO && (
										<DealerList
											ghost={true}
											mode={'detail'}
											dealerId={dealerVO.dealerId}
											trigger={() => (
												<Space>
													<a>{dealerVO.shortName}</a>
												</Space>
											)}
										/>
									)
								);
							},
						},
						supplier: {
							render: (supplierVO: BusinessAPI.SupplierVO) => {
								return (
									supplierVO && (
										<SupplierFarmerList
											ghost={true}
											mode={'detail'}
											supplierId={supplierVO.supplierId}
											trigger={() => (
												<Space>
													<a>{supplierVO.name}</a>
												</Space>
											)}
										/>
									)
								);
							},
						},
						order: {
							renderFormItem: (_, props) => {
								return <OrderFormItem {...props} {...props?.fieldProps} />;
							},
							render: (orderVO: BusinessAPI.OrderVO) => {
								return (
									orderVO && (
										<OrderList
											ghost={true}
											mode={'detail'}
											orderId={orderVO.orderId}
											trigger={() => (
												<Space>
													<a>
														{`${orderVO.orderVehicle?.dealerName} - 第 ${orderVO.orderVehicle?.vehicleNo || '暂无'} 车 - ${orderVO.orderSn || '暂无'}`}
													</a>
												</Space>
											)}
										/>
									)
								);
							},
						},
						user: {
							renderFormItem: (_, props) => {
								return <UserFormItem {...props} {...props?.fieldProps} />;
							},
							render: (userVO: BusinessAPI.UserVO) => {
								return (
									userVO && (
										<UserList
											ghost={true}
											mode={'detail'}
											userId={userVO.userId}
											trigger={() => (
												<Space>
													<Avatar
														src={userVO?.avatar}
														icon={<UserOutlined />}
														size={24}
													/>
													<a>{userVO.nickname || userVO.name}</a>
												</Space>
											)}
										/>
									)
								);
							},
						},
						remark: {
							renderFormItem: (_, props) => {
								return <RemarkFormItem {...props} {...props?.fieldProps} />;
							},
							render: (remark: string, props) => {
								// @ts-ignore
								const { record } = props;
								return (
									<Remark remark={remark} {...record} {...props?.fieldProps} />
								);
							},
						},
					},
				}}
			>
				<RouteContext.Consumer>
					{(value: RouteContextType) => {
						const { isMobile } = value;
						return render(isMobile);
					}}
				</RouteContext.Consumer>
			</ProProvider.Provider>
		);
	};

	if (ghost) {
		return renderContext();
	}

	return (
		<PageContainer
			permission={permission + '-view'}
			fieldProps={{
				...containerProps,
				extra: [
					containerProps?.extra,
					tour && (
						<Tour
							key={'tour1'}
							open={openTour}
							onClose={() => {
								setOpenTour(false);
								setCurrentStep(0);
							}}
							steps={tourSteps}
							current={currentStep}
							onChange={setCurrentStep}
							indicatorsRender={(current, total) => (
								<span>
									{current + 1} / {total}
								</span>
							)}
						/>
					),
					tour && (
						<Button
							key={'tour2'}
							onClick={() => {
								initTour(tour);
								setOpenTour(true);
							}}
							type={'link'}
							size={'small'}
						>
							打开引导
						</Button>
					),
				],
			}}
		>
			{renderContext()}
		</PageContainer>
	);
}
