import { ProFormFieldProps, ProFormItem } from '@ant-design/pro-components';
import { Form, Space } from 'antd';
import React from 'react';
import {
	DragDropContext,
	Draggable,
	Droppable,
	DropResult,
} from 'react-beautiful-dnd';

interface BizDragDropProps<T> {
	/**
	 * 表单项属性
	 */
	fieldProps?: ProFormFieldProps;
	/**
	 * 可拖拽区域的ID
	 */
	droppableId: string;
	/**
	 * 用作唯一标识的字段名
	 */
	rowKey: keyof T;
	/**
	 * 数据源
	 */
	value: T[];
	/**
	 * 数据变化回调
	 */
	onChange: (value: T[]) => void;
	/**
	 * 自定义渲染函数
	 */
	render: (item: T, index: number) => React.ReactNode;
	/**
	 * 排序方向
	 * @default horizontal
	 */
	direction?: 'horizontal' | 'vertical';
	/**
	 * 自定义容器样式
	 */
	containerStyle?: React.CSSProperties;
	/**
	 * 自定义项样式
	 */
	itemStyle?: React.CSSProperties;
	/**
	 * 拖拽开始回调
	 */
	onDragStart?: () => void;
	/**
	 * 拖拽结束回调
	 */
	onDragEnd?: (result: DropResult) => void;
	/**
	 * 表单字段名称，用于直接更新表单数据
	 */
	name?: string | string[];
	/**
	 * 需要同时更新的其他表单字段及值
	 */
	relatedFields?: Record<string, any>;
}

export default function BizDragDrop<T>(props: BizDragDropProps<T>) {
	const {
		fieldProps,
		droppableId,
		rowKey,
		value,
		onChange,
		render,
		direction = 'horizontal',
		containerStyle,
		itemStyle,
		onDragStart,
		onDragEnd,
		name,
		relatedFields,
	} = props;

	// 获取当前表单实例（始终调用，避免条件性Hook调用）
	const form = Form.useFormInstance();

	// 重新排列数组元素
	const reorder = (list: T[], startIndex: number, endIndex: number): T[] => {
		const result = Array.from(list);
		const [removed] = result.splice(startIndex, 1);
		result.splice(endIndex, 0, removed);
		return result;
	};

	const handleDragStart = () => {
		onDragStart?.();
	};

	const handleDragEnd = (result: DropResult) => {
		onDragEnd?.(result);

		// 如果没有移动到有效位置，直接返回
		if (
			!result.destination ||
			result.source.index === result.destination.index
		) {
			return;
		}

		const reorderedList = reorder(
			value,
			result.source.index,
			result.destination.index,
		);

		// 如果提供了表单字段名称且表单实例存在，直接更新表单数据
		if (name && form) {
			// 更新主字段
			form.setFieldValue(name, reorderedList);

			// 更新相关字段
			if (relatedFields) {
				Object.keys(relatedFields).forEach((fieldName) => {
					const fieldValue =
						typeof relatedFields[fieldName] === 'function'
							? relatedFields[fieldName](reorderedList)
							: relatedFields[fieldName];
					form.setFieldValue(fieldName, fieldValue);
				});
			}
		}

		onChange?.(reorderedList);
	};

	// 默认容器样式
	const defaultContainerStyle: React.CSSProperties = {
		display: 'flex',
		flexWrap: 'wrap',
		gap: 8,
		padding: '8px',
		minHeight: '40px',
		border: '1px dashed #d9d9d9',
		borderRadius: '4px',
		backgroundColor: '#fafafa',
		...(direction === 'vertical' ? { flexDirection: 'column' } : {}),
		...containerStyle,
	};

	// 默认项样式
	const defaultItemStyle = (isDragging: boolean): React.CSSProperties => ({
		background: isDragging ? '#e6f7ff' : '#ffffff',
		border: isDragging ? '1px dashed #1890ff' : '1px solid #d9d9d9',
		borderRadius: '4px',
		padding: '8px 12px',
		boxShadow: isDragging
			? '0 2px 8px rgba(0,0,0,0.15)'
			: '0 1px 2px rgba(0,0,0,0.05)',
		cursor: 'move',
		userSelect: 'none',
		display: 'flex',
		alignItems: 'center',
		gap: 4,
		...itemStyle,
	});

	return (
		<DragDropContext onDragEnd={handleDragEnd} onDragStart={handleDragStart}>
			<ProFormItem
				name={name}
				{...fieldProps}
				style={{
					width: '100%',
					...fieldProps?.style,
				}}
			>
				<Droppable droppableId={droppableId} direction={direction}>
					{(provided) => (
						<div
							{...provided.droppableProps}
							ref={provided.innerRef}
							style={defaultContainerStyle}
						>
							{value.map((item, index) => (
								<Draggable
									key={String(item[rowKey])}
									draggableId={String(item[rowKey])}
									index={index}
								>
									{(provided, snapshot) => (
										<div
											ref={provided.innerRef}
											{...provided.draggableProps}
											{...provided.dragHandleProps}
											style={{
												...provided.draggableProps.style,
												...defaultItemStyle(snapshot.isDragging),
											}}
										>
											<span style={{ cursor: 'grab' }}>⠿</span>
											<Space size={4}>{render(item, index)}</Space>
										</div>
									)}
								</Draggable>
							))}
							{provided.placeholder}
						</div>
					)}
				</Droppable>
			</ProFormItem>
		</DragDropContext>
	);
}
