<script lang="ts" setup>
import { ref, onBeforeUnmount } from 'vue';

import { useVbenModal } from '@vben/common-ui';
import { Icon } from '#/components/icon';

import { message } from 'ant-design-vue';

import { updateHomeZonesSortOrder, getHomeZonesList, getHomeZonesOption } from '../api';

const [Modal, modalApi] = useVbenModal({
  fullscreenButton: false,
  draggable: true,
  onCancel() {
    modalApi.close();
  },
  onConfirm: async () => {
    const ids = sortableList.value.map((item) => item.id);
    if (!ids.length) {
      message.warning('没有可排序的数据');
      return;
    }
    modalApi.setState({ loading: true, confirmLoading: true });
    updateHomeZonesSortOrder({ ids })
      .then(() => {
        message.success('排序更新成功');
        const gridApi = modalApi.getData()?.gridApi;
        if (gridApi) {
          gridApi.query();
        }
        modalApi.close();
      })
      .catch(() => {
        message.error('排序更新失败');
      })
      .finally(() => {
        modalApi.setState({ loading: false, confirmLoading: false });
      });
  },
  onOpenChange(isOpen: boolean) {
    if (isOpen) {
      loadZonesList();
    } else {
      sortableList.value = [];
    }
  },
});

const sortableList = ref<any[]>([]);

const loadZonesList = async () => {
  try {
    // 先尝试使用list接口获取所有数据
    const res = await getHomeZonesList({
      page: 1,
      pageSize: 1000, // 获取所有数据用于排序
    });

    // 尝试多种可能的数据路径
    let data = [];
    if (Array.isArray(res?.items)) {
      data = res.items;
    }

    // 如果list接口没有数据，尝试使用option接口
    if (data.length === 0) {
      try {
        const optionRes = await getHomeZonesOption();
        if (Array.isArray(optionRes?.data?.data)) {
          data = optionRes.data.data;
        } else if (Array.isArray(optionRes?.data?.result)) {
          data = optionRes.data.result;
        } else if (Array.isArray(optionRes?.data)) {
          data = optionRes.data;
        }
      } catch (optionError) {
        console.error('option接口调用失败:', optionError);
      }
    }

    // 调试：如果还是没有数据，输出调试信息
    if (data.length === 0) {
      console.log('API响应数据:', res);
      message.warning('暂无数据可排序');
    }

    // 按 sort_order 排序
    sortableList.value = [...data].sort((a, b) => (a.sort_order || 0) - (b.sort_order || 0));
  } catch (error) {
    console.error('加载数据失败:', error);
    message.error('加载数据失败');
  }
};

// 拖拽相关
const draggedIndex = ref(-1);
const dragOverIndex = ref(-1);

const onDragStart = (event: DragEvent, index: number) => {
  draggedIndex.value = index;
  dragOverIndex.value = -1;
  if (event.dataTransfer) {
    event.dataTransfer.effectAllowed = 'move';
  }
};

// 使用 dragenter 来更新目标索引，避免反复闪烁
const onDragEnter = (index: number) => {
  if (draggedIndex.value !== -1 && draggedIndex.value !== index) {
    dragOverIndex.value = index;
  }
};

// dragover 必须阻止默认行为以允许 drop
const onDragOver = (event: DragEvent) => {
  event.preventDefault();
  if (event.dataTransfer) {
    event.dataTransfer.dropEffect = 'move';
  }
};

const onDrop = (event: DragEvent, targetIndex: number) => {
  event.preventDefault();
  // 如果没有拖拽或目标是自己，直接重置
  if (draggedIndex.value === -1 || draggedIndex.value === targetIndex) {
    draggedIndex.value = -1;
    dragOverIndex.value = -1;
    return;
  }

  const list = [...sortableList.value];
  const itemToMove = list[draggedIndex.value];

  // 从原位置移除
  list.splice(draggedIndex.value, 1);

  // 计算插入位置：如果从前往后拖，由于原位置被删除了，目标索引会自动前移，所以不需要特殊处理
  // 但如果直接使用 targetIndex，在 draggedIndex < targetIndex 的情况下，插入位置会是 targetIndex - 1 (逻辑上)
  // 这里的逻辑：我们希望它出现在 targetIndex 指定的元素位置（即代替它，把它挤下去）
  // 简单的 splice 逻辑如下：
  // 如果移除的元素在目标之前，目标元素的索引会减1，所以我们需要插入到修正后的位置？
  // 实际上，Vue的列表渲染中，如果我们在 targetIndex 处插入，它会变成新的 targetIndex 元素。
  // 由于我们是"插入到目标之前"(placeholder显示在前面)，所以直接用 targetIndex 稍微调整即可。

  // 修正目标索引逻辑：
  // 既然视觉上是插入到 targetIndex 的"前面" (Placeholder位置)，
  // 如果 draggedIndex < targetIndex，移除 draggedIndex 后，原本的 targetIndex 会变成 targetIndex - 1。
  // 此时我们应该插入到 targetIndex - 1 的位置。
  // 如果 draggedIndex > targetIndex，移除后 targetIndex 不变，直接插入。

  let finalIndex = targetIndex;
  if (draggedIndex.value < targetIndex) {
    finalIndex = targetIndex - 1;
  }

  list.splice(finalIndex, 0, itemToMove);

  sortableList.value = list;
  draggedIndex.value = -1;
  dragOverIndex.value = -1;
};

const onDragEnd = () => {
  draggedIndex.value = -1;
  dragOverIndex.value = -1;
};

const getTypeLabel = (type: string) => {
  const map: Record<string, string> = {
    otc: 'OTC专区',
    prescription: '处方药专区',
    health_food: '保健食品专区',
    service_package: '产品服务包专区',
  };
  return map[type] || type || '-';
};
</script>

<template>
  <Modal title="拖拽排序" class="w-[600px]">
    <div class="py-5">
      <div class="mb-5 rounded-md bg-blue-50 px-4 py-3 dark:bg-blue-900/20 border-l-4 border-blue-500 dark:border-blue-400">
        <p class="m-0 text-sm text-gray-600 dark:text-gray-300">提示：拖拽列表项可调整排序，数字越小越靠前</p>
      </div>
      <div class="max-h-[500px] overflow-y-auto">
        <template v-for="(item, index) in sortableList" :key="item.id">
          <!-- 占位符卡片：显示在拖拽目标位置 -->
          <div
            v-if="dragOverIndex === index && draggedIndex !== -1 && draggedIndex !== index"
            class="mb-3 rounded-lg border-2 border-dashed border-blue-500 bg-blue-50/50 dark:bg-blue-900/30 dark:border-blue-400 transition-all"
            @dragenter="onDragEnter(index)"
            @dragover="onDragOver"
            @drop="onDrop($event, index)"
          >
            <div class="flex items-center gap-4 p-4 opacity-60 pointer-events-none">
              <div class="flex h-8 w-8 items-center justify-center text-blue-500 dark:text-blue-400">
                <Icon icon="ant-design:menu-outlined" class="text-xl" />
              </div>
              <div class="flex-1 min-w-0">
                <div class="mb-1.5 text-base font-medium text-blue-700 dark:text-blue-300">
                  {{ sortableList[draggedIndex]?.title || '拖拽项' }}
                </div>
                <div class="flex items-center gap-4 text-sm text-blue-600 dark:text-blue-400">
                  <span class="rounded px-2 py-0.5 bg-blue-100 text-blue-700 dark:bg-blue-800/50 dark:text-blue-300">
                    {{ getTypeLabel(sortableList[draggedIndex]?.type) }}
                  </span>
                  <span>释放以插入此处</span>
                </div>
              </div>
              <div class="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-blue-200 text-sm font-medium text-blue-700 dark:bg-blue-800 dark:text-blue-300">
                {{ index + 1 }}
              </div>
            </div>
          </div>

          <!-- 列表项 -->
          <div
            :class="[
              'mb-3 rounded-lg border transition-all duration-300 ease-in-out',
              {
                // 正在拖拽的项：半透明
                'opacity-30': draggedIndex === index,
                // 普通状态
                'cursor-move border-gray-200 bg-white hover:border-blue-500 hover:shadow-md dark:border-gray-700 dark:bg-gray-800 dark:hover:border-blue-400 dark:hover:shadow-lg': draggedIndex === -1 || (draggedIndex !== index && dragOverIndex !== index),
                // 拖拽悬停目标上方：向下移动
                'translate-y-2 border-gray-300 dark:border-gray-600': dragOverIndex === index && draggedIndex !== -1 && draggedIndex !== index && draggedIndex < index,
                // 拖拽悬停目标下方：向上移动
                '-translate-y-2 border-gray-300 dark:border-gray-600': dragOverIndex === index && draggedIndex !== -1 && draggedIndex !== index && draggedIndex > index,
              }
            ]"
            draggable="true"
            @dragstart="onDragStart($event, index)"
            @dragenter="onDragEnter(index)"
            @dragover="onDragOver"
            @drop="onDrop($event, index)"
            @dragend="onDragEnd"
          >
            <div class="flex items-center gap-4 p-4 pointer-events-none">
              <!-- 添加 pointer-events-none 到内部容器，确保拖拽事件只由外层div触发，防止子元素干扰 -->
              <div class="flex h-8 w-8 items-center justify-center text-gray-500 dark:text-gray-400 transition-colors pointer-events-auto">
                <!-- 图标区域重新开启指针事件，以便可以选中（如果有需要），或者保持none -->
                <Icon icon="ant-design:menu-outlined" class="text-xl" />
              </div>
              <div class="flex-1 min-w-0">
                <div class="mb-1.5 text-base font-medium text-gray-900 dark:text-gray-100">{{ item.title }}</div>
                <div class="flex items-center gap-4 text-sm text-gray-500 dark:text-gray-400">
                  <span class="rounded px-2 py-0.5 bg-blue-50 text-blue-600 dark:bg-blue-900/30 dark:text-blue-400">{{ getTypeLabel(item.type) }}</span>
                  <span class="text-gray-600 dark:text-gray-300">当前排序：{{ item.sort_order || 0 }}</span>
                </div>
              </div>
              <div class="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-gray-100 text-sm font-medium text-gray-600 dark:bg-gray-700 dark:text-gray-300">
                {{ index + 1 }}
              </div>
            </div>
          </div>
        </template>
        <div v-if="sortableList.length === 0" class="py-10 text-center text-sm text-gray-500 dark:text-gray-400">
          暂无数据
        </div>
      </div>
    </div>
  </Modal>
</template>
