import { PlusOutlined } from '@ant-design/icons';
import {
  DndContext,
  type DragEndEvent,
  type DragOverEvent,
  DragOverlay,
  type DragStartEvent,
  PointerSensor,
  useSensor,
  useSensors,
} from '@dnd-kit/core';
import { rectSortingStrategy, SortableContext } from '@dnd-kit/sortable';
import { Button, Form, Input, Modal, message, Space, Switch } from 'antd';
import React, { useCallback, useMemo, useState } from 'react';
import DragOverlayTag from '../DragOverlayTag';
import { SortableTag } from '../SortableTag';
import type { TagItem } from '../types';
import './index.less';

const DraggableTagList: React.FC = () => {
  const [tags, setTags] = useState<TagItem[]>([
    { id: '1', label: '标签1', disabled: false, sort: 1 },
    { id: '2', label: '标签2', disabled: false, sort: 2 },
    { id: '3', label: '标签3', disabled: true, sort: 3 },
    { id: '4', label: '标签4', disabled: false, sort: 4 },
    { id: '5', label: '标签5', disabled: false, sort: 5 },
  ]);

  const [isModalVisible, setIsModalVisible] = useState(false);
  const [editingTag, setEditingTag] = useState<TagItem | null>(null);
  const [activeId, setActiveId] = useState<string | null>(null);
  const [overId, setOverId] = useState<string | null>(null);
  const [form] = Form.useForm();

  // 优化传感器配置
  const sensors = useSensors(
    useSensor(PointerSensor, {
      activationConstraint: {
        distance: 8,
      },
    }),
  );

  // 创建标签映射，避免重复查找
  const tagMap = useMemo(() => {
    const map = new Map<string, TagItem>();
    tags.forEach((tag) => {
      map.set(tag.id, tag);
    });
    return map;
  }, [tags]);

  // 拖拽开始 - 使用 useCallback 避免重复创建
  const handleDragStart = useCallback(
    (event: DragStartEvent) => {
      const { active } = event;
      const activeTag = tagMap.get(active.id as string);

      if (activeTag?.disabled) {
        return;
      }

      setActiveId(active.id as string);
    },
    [tagMap],
  );

  // 拖拽取消
  const handleDragCancel = useCallback(() => {
    setActiveId(null);
    setOverId(null);
  }, []);

  // 优化拖拽经过 - 减少不必要的状态更新
  const handleDragOver = useCallback(
    (event: DragOverEvent) => {
      const { over, active } = event;

      // 如果没有 over 或 active，清除 overId
      if (!over || !active) {
        if (overId !== null) {
          setOverId(null);
        }
        return;
      }

      const newOverId = over.id as string;

      // 如果 overId 没有变化，不更新状态
      if (newOverId === overId) {
        return;
      }

      const activeTag = tagMap.get(active.id as string);
      const overTag = tagMap.get(newOverId);

      // 检查是否可以高亮
      if (
        !activeTag ||
        activeTag.disabled ||
        !overTag ||
        overTag.disabled ||
        newOverId === active.id
      ) {
        if (overId !== null) {
          setOverId(null);
        }
        return;
      }

      setOverId(newOverId);
    },
    [overId, tagMap],
  );

  // 拖拽结束 - 使用 useCallback
  const handleDragEnd = useCallback((event: DragEndEvent) => {
    const { active, over } = event;

    setActiveId(null);
    setOverId(null);

    if (!over || active.id === over.id) {
      return;
    }

    setTags((items) => {
      const activeIndex = items.findIndex((item) => item.id === active.id);
      const overIndex = items.findIndex((item) => item.id === over.id);

      if (activeIndex === -1 || overIndex === -1) {
        return items;
      }

      if (items[activeIndex].disabled) {
        message.warning('禁用的标签不可拖拽');
        return items;
      }

      if (items[overIndex].disabled) {
        message.warning('不能与禁用的标签交换位置');
        return items;
      }

      const newItems = [...items];

      // 交换sort值
      const tempSort = newItems[activeIndex].sort;
      newItems[activeIndex] = {
        ...newItems[activeIndex],
        sort: newItems[overIndex].sort,
      };
      newItems[overIndex] = {
        ...newItems[overIndex],
        sort: tempSort,
      };

      // 交换位置
      [newItems[activeIndex], newItems[overIndex]] = [
        newItems[overIndex],
        newItems[activeIndex],
      ];

      message.success('交换成功');
      return newItems;
    });
  }, []);

  // 添加标签
  const handleAddTag = useCallback(() => {
    setEditingTag(null);
    form.resetFields();
    setIsModalVisible(true);
  }, [form]);

  // 编辑标签
  const handleEditTag = useCallback(
    (tag: TagItem) => {
      setEditingTag(tag);
      form.setFieldsValue(tag);
      setIsModalVisible(true);
    },
    [form],
  );

  // 删除标签
  const handleDeleteTag = useCallback((id: string) => {
    setTags((prevTags) => prevTags.filter((tag) => tag.id !== id));
    message.success('删除成功');
  }, []);

  // 保存标签
  const handleSaveTag = useCallback(async () => {
    try {
      const values = await form.validateFields();

      if (editingTag) {
        setTags((prevTags) =>
          prevTags.map((tag) =>
            tag.id === editingTag.id ? { ...tag, ...values } : tag,
          ),
        );
        message.success('编辑成功');
      } else {
        setTags((prevTags) => {
          const maxSort = Math.max(...prevTags.map((t) => t.sort), 0);
          const newTag: TagItem = {
            id: Date.now().toString(),
            disabled: false,
            sort: maxSort + 1,
            ...values,
          };
          return [...prevTags, newTag];
        });
        message.success('添加成功');
      }

      setIsModalVisible(false);
      form.resetFields();
    } catch (error) {
      console.error('验证失败:', error);
    }
  }, [editingTag, form]);

  // 获取当前拖拽的标签
  const activeTag = useMemo(
    () => (activeId ? tagMap.get(activeId) : null),
    [activeId, tagMap],
  );

  // 生成 sortable items
  const sortableItems = useMemo(() => tags.map((tag) => tag.id), [tags]);

  return (
    <div className="draggable-tag-list">
      <Space direction="vertical" style={{ width: '100%' }} size="large">
        <Button type="dashed" icon={<PlusOutlined />} onClick={handleAddTag}>
          添加标签
        </Button>

        <DndContext
          sensors={sensors}
          onDragStart={handleDragStart}
          onDragOver={handleDragOver}
          onDragEnd={handleDragEnd}
          onDragCancel={handleDragCancel}
        >
          <SortableContext items={sortableItems} strategy={rectSortingStrategy}>
            <div className="tag-container">
              {tags.map((tag) => (
                <SortableTag
                  key={tag.id}
                  tag={tag}
                  isActive={activeId === tag.id}
                  isOver={overId === tag.id}
                  onEdit={handleEditTag}
                  onDelete={handleDeleteTag}
                />
              ))}
            </div>
          </SortableContext>

          <DragOverlay dropAnimation={null}>
            {activeTag ? <DragOverlayTag tag={activeTag} /> : null}
          </DragOverlay>
        </DndContext>

        <div className="sort-info">
          <h4>当前排序：</h4>
          <div className="sort-list">
            {tags.map((tag) => (
              <span key={tag.id} className="sort-item">
                {tag.label} (sort: {tag.sort})
              </span>
            ))}
          </div>
        </div>
      </Space>

      <Modal
        title={editingTag ? '编辑标签' : '添加标签'}
        open={isModalVisible}
        onOk={handleSaveTag}
        onCancel={() => {
          setIsModalVisible(false);
          form.resetFields();
        }}
        okText="确定"
        cancelText="取消"
      >
        <Form form={form} layout="vertical">
          <Form.Item
            name="label"
            label="标签名称"
            rules={[
              { required: true, message: '请输入标签名称' },
              { max: 20, message: '标签名称不能超过20个字符' },
            ]}
          >
            <Input placeholder="请输入标签名称" maxLength={20} />
          </Form.Item>

          <Form.Item
            name="disabled"
            label="禁用状态"
            valuePropName="checked"
            initialValue={false}
            tooltip="禁用后的标签不可拖拽、不可删除、不可作为交换目标"
          >
            <Switch checkedChildren="禁用" unCheckedChildren="启用" />
          </Form.Item>
        </Form>
      </Modal>
    </div>
  );
};

export default DraggableTagList;
