<template>
  <!-- 菜单排序抽屉 -->
  <el-drawer
    v-model="visibleProxy"
    title="菜单排序管理"
    size="60%"
    append-to-body
    :close-on-click-modal="false"
    @closed="handleDrawerClose"
    class="menu-sort-drawer"
  >
    <!-- 抽屉头部操作栏 -->
    <template #header="{ titleId, titleClass }">
      <div class="drawer-header">
        <h4 :id="titleId" :class="titleClass" class="drawer-title">
          <el-icon class="title-icon"><Sort /></el-icon>
          菜单排序管理
          <el-badge
            v-if="hasChanges"
            value="已修改"
            type="warning"
            class="ml-2"
          />
        </h4>
        <div class="header-description">
          拖拽调整菜单顺序，支持跨层级移动
        </div>
      </div>
    </template>

    <!-- 抽屉内容 -->
    <div class="drawer-content">
      <!-- 操作提示 -->
      <el-alert
        title="操作提示"
        type="info"
        :closable="false"
        show-icon
        class="mb-3"
      >
        <template #default>
          <div class="tips-content">
            <span><el-icon><InfoFilled /></el-icon> 拖拽菜单节点可调整排序，支持同级排序和跨层级移动</span>
            <span><el-icon><WarningFilled /></el-icon> 排序后需要点击"保存"按钮才能生效</span>
          </div>
        </template>
      </el-alert>

      <!-- 菜单排序树 -->
      <el-card shadow="hover" class="sort-tree-card">
        <template #header>
          <div class="card-header">
            <div class="header-title">
              <el-icon><Menu /></el-icon>
              <span>菜单排序树</span>
            </div>
            <div class="header-controls">
              <div class="tree-stats">
                <el-tag size="small" type="info">
                  共 {{ totalMenuCount }} 个菜单
                </el-tag>
              </div>
              <div class="tree-actions">
                <el-button-group size="small">
                  <el-tooltip content="展开全部" placement="top">
                    <el-button
                      :type="isExpandAll ? 'primary' : 'default'"
                      icon="Plus"
                      @click="toggleExpandAll"
                    >
                      {{ isExpandAll ? '收缩' : '展开' }}
                    </el-button>
                  </el-tooltip>

                  <el-tooltip content="重置排序" placement="top">
                    <el-button
                      type="warning"
                      icon="RefreshLeft"
                      @click="handleReset"
                      :loading="resetLoading"
                    >
                      重置
                    </el-button>
                  </el-tooltip>
                </el-button-group>
              </div>
            </div>
          </div>
        </template>

        <div v-loading="treeLoading" class="sort-tree-container">
          <el-tree
            ref="sortTreeRef"
            :data="treeData"
            node-key="menuId"
            :props="treeProps"
            :default-expand-all="isExpandAll"
            :draggable="true"
            :allow-drop="allowDrop"
            :allow-drag="allowDrag"
            @node-drop="handleNodeDrop"
            class="sort-tree"
          >
            <template #default="{ node, data }">
              <div class="custom-tree-node">
                <div class="node-content">
                  <!-- 菜单图标和类型 -->
                  <div class="node-icon">
                    <el-icon v-if="data.menuType === 'M'" class="type-icon directory">
                      <Folder />
                    </el-icon>
                    <el-icon v-else-if="data.menuType === 'C'" class="type-icon menu">
                      <Document />
                    </el-icon>
                    <el-icon v-else class="type-icon button">
                      <Operation />
                    </el-icon>
                  </div>

                  <!-- 菜单信息 -->
                  <div class="node-info">
                    <span class="menu-name">{{ data.menuName }}</span>
                    <el-tag
                      :type="getMenuTypeTag(data.menuType)"
                      size="small"
                      class="type-tag"
                    >
                      {{ getMenuTypeName(data.menuType) }}
                    </el-tag>
                  </div>
                </div>

                <!-- 拖拽指示器 -->
                <div class="drag-indicator">
                  <el-icon><Rank /></el-icon>
                </div>
              </div>
            </template>
          </el-tree>

          <!-- 空数据提示 -->
          <el-empty
            v-if="!treeLoading && (!treeData || treeData.length === 0)"
            description="暂无菜单数据"
            :image-size="100"
          >
            <el-button type="primary" @click="loadTreeData">
              重新加载
            </el-button>
          </el-empty>
        </div>
      </el-card>
    </div>

    <!-- 抽屉底部操作按钮 -->
    <template #footer>
      <div class="drawer-footer">
        <el-button
          :loading="saveLoading"
          type="primary"
          @click="handleSave"
          :disabled="!hasChanges"
        >
          <el-icon><Check /></el-icon>
          保存排序
        </el-button>
        <el-button @click="handleCancel">
          取消
        </el-button>
      </div>
    </template>
  </el-drawer>
</template>

<script setup lang="ts">
import { getSortTree, sortMenu } from '@/api/system/menu';
import { MenuSortRequest, MenuSortVO } from '@/api/system/menu/types';
import {
  Check,
  Document,
  Folder,
  InfoFilled,
  Menu,
  Operation,
  Rank,
  Sort,
  WarningFilled
} from '@element-plus/icons-vue';

// ==================== Props 和 Emits ====================
const props = defineProps({
  visible: {
    type: Boolean,
    default: false
  }
});

const emit = defineEmits(['update:visible', 'save']);

const { proxy } = getCurrentInstance() as ComponentInternalInstance;

// ==================== 响应式数据 ====================
// 可见性双向绑定
const visibleProxy = computed({
  get: () => props.visible,
  set: (val) => emit('update:visible', val)
});

// 树形数据
const treeData = ref<MenuSortVO[]>([]);
const treeLoading = ref(false);
const sortTreeRef = ref<ElTreeInstance>();

// 控制状态
const isExpandAll = ref(true);
const hasChanges = ref(false);
const saveLoading = ref(false);
const resetLoading = ref(false);

// 树属性配置
const treeProps = {
  children: 'children',
  label: 'menuName'
};

// ==================== 计算属性 ====================
const totalMenuCount = computed(() => {
  return countMenuNodes(treeData.value);
});

// ==================== 滚动修复方法 ====================

/**
 * 强制刷新滚动容器
 */
const refreshScrollContainer = () => {
  nextTick(() => {
    const container = document.querySelector('.sort-tree-container');
    if (container) {
      // 临时改变高度触发重新计算
      const originalHeight = container.style.height;
      container.style.height = 'auto';
      container.offsetHeight; // 触发重流
      container.style.height = originalHeight;

      // 检查是否需要滚动条
      if (container.scrollHeight > container.clientHeight) {
        container.style.overflowY = 'auto';
      }
    }
  });
};

/**
 * 计算并设置容器高度
 */
const calculateContainerHeight = () => {
  nextTick(() => {
    const drawer = document.querySelector('.menu-sort-drawer .el-drawer__body');
    const content = document.querySelector('.drawer-content');
    const alert = document.querySelector('.drawer-content .el-alert');
    const cardHeader = document.querySelector('.sort-tree-card .el-card__header');
    const footer = document.querySelector('.drawer-footer');

    if (drawer && content && alert && cardHeader && footer) {
      const drawerHeight = drawer.clientHeight;
      const alertHeight = alert.offsetHeight;
      const cardHeaderHeight = cardHeader.offsetHeight;
      const footerHeight = footer.offsetHeight;
      const padding = 60; // 各种padding和margin的总和

      const availableHeight = drawerHeight - alertHeight - cardHeaderHeight - footerHeight - padding;

      const container = document.querySelector('.sort-tree-container');
      if (container && availableHeight > 100) {
        container.style.maxHeight = `${availableHeight}px`;
        container.style.overflowY = 'auto';
      }
    }
  });
};

/**
 * 防抖函数
 */
const debounce = (func, wait) => {
  let timeout;
  return function executedFunction(...args) {
    const later = () => {
      clearTimeout(timeout);
      func(...args);
    };
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
  };
};

/**
 * 监听窗口大小变化
 */
const handleResize = debounce(() => {
  calculateContainerHeight();
  refreshScrollContainer();
}, 300);

// ==================== 监听器 ====================
watch(() => props.visible, (newVal) => {
  if (newVal) {
    loadTreeData();
    resetState();

    // 抽屉打开后计算高度
    setTimeout(() => {
      calculateContainerHeight();
      refreshScrollContainer();
    }, 300);
  }
});

// 监听treeData变化
watch(() => treeData.value, () => {
  nextTick(() => {
    setTimeout(() => {
      refreshScrollContainer();
    }, 100);
  });
}, { deep: true });

// ==================== 方法 ====================

/**
 * 重置状态
 */
const resetState = () => {
  hasChanges.value = false;
  isExpandAll.value = true;
};

/**
 * 加载树形数据
 */
const loadTreeData = async () => {
  treeLoading.value = true;
  try {
    const response = await getSortTree();
    if (response.code === 200 && response.data) {
      // 过滤掉按钮类型的菜单
      treeData.value = filterButtonMenus(response.data);
      resetState();

      // 数据加载完成后刷新滚动容器
      await nextTick();
      setTimeout(() => {
        calculateContainerHeight();
        refreshScrollContainer();
      }, 100);
    } else {
      proxy?.$modal.msgError(response.msg || '获取菜单数据失败');
    }
  } catch (error) {
    proxy?.$modal.msgError('加载菜单数据失败');
  } finally {
    treeLoading.value = false;
  }
};

/**
 * 过滤掉按钮类型的菜单
 */
const filterButtonMenus = (menus: MenuSortVO[]): MenuSortVO[] => {
  return menus
    .filter(menu => menu.menuType !== 'F') // 过滤掉按钮类型
    .map(menu => ({
      ...menu,
      children: menu.children ? filterButtonMenus(menu.children) : []
    }));
};

/**
 * 统计菜单节点数量
 */
const countMenuNodes = (nodes: MenuSortVO[]): number => {
  let count = 0;
  nodes.forEach(node => {
    count++;
    if (node.children && node.children.length > 0) {
      count += countMenuNodes(node.children);
    }
  });
  return count;
};

/**
 * 切换展开/收缩状态
 */
const toggleExpandAll = () => {
  isExpandAll.value = !isExpandAll.value;

  nextTick(() => {
    if (sortTreeRef.value) {
      const allNodes = sortTreeRef.value.store.nodesMap;
      Object.values(allNodes).forEach((node: any) => {
        node.expanded = isExpandAll.value;
      });

      // 展开/收缩后刷新滚动
      setTimeout(() => {
        refreshScrollContainer();
      }, 300); // 等待动画完成
    }
  });
};

/**
 * 判断是否允许拖拽
 */
const allowDrag = (draggingNode: any) => {
  return true;
};

/**
 * 判断是否允许放置
 */
const allowDrop = (draggingNode: any, dropNode: any, type: string) => {
  // 不允许拖拽到按钮节点下面
  if (type === 'inner' && dropNode.data.menuType === 'F') {
    return false;
  }

  // 不允许拖拽到自己的子节点下面
  if (type === 'inner' && isDescendant(draggingNode.data, dropNode.data)) {
    return false;
  }

  return true;
};

/**
 * 判断是否为子孙节点
 */
const isDescendant = (ancestor: MenuSortVO, node: MenuSortVO): boolean => {
  if (!ancestor.children) return false;

  for (const child of ancestor.children) {
    if (child.menuId === node.menuId) {
      return true;
    }
    if (isDescendant(child, node)) {
      return true;
    }
  }
  return false;
};

/**
 * 处理节点拖拽
 */
const handleNodeDrop = (draggingNode: any, dropNode: any, dropType: string, ev: Event) => {
  hasChanges.value = true;

  // 重新计算排序号
  recalculateOrderNums(treeData.value);

  proxy?.$modal.msgSuccess('拖拽完成，请保存修改');
};

/**
 * 重新计算排序号
 */
const recalculateOrderNums = (nodes: MenuSortVO[], startNum: number = 1) => {
  nodes.forEach((node, index) => {
    node.orderNum = startNum + index;
    if (node.children && node.children.length > 0) {
      recalculateOrderNums(node.children, 1);
    }
  });
};

/**
 * 保存排序
 */
const handleSave = async () => {
  if (!hasChanges.value) {
    proxy?.$modal.msgInfo('没有需要保存的更改');
    return;
  }

  saveLoading.value = true;
  try {
    // 构建保存数据
    const sortData = buildSortData(treeData.value);

    const response = await sortMenu(sortData);
    if (response.code === 200) {
      hasChanges.value = false;

      proxy?.$modal.msgSuccess(response.msg || '保存成功');
      emit('save'); // 通知父组件刷新数据
      visibleProxy.value = false; // 关闭抽屉
    } else {
      proxy?.$modal.msgError(response.msg || '保存失败');
    }
  } catch (error) {
    proxy?.$modal.msgError('保存失败，请稍后重试');
  } finally {
    saveLoading.value = false;
  }
};

/**
 * 构建保存数据
 */
const buildSortData = (nodes: MenuSortVO[], parentId: number = 0): MenuSortRequest[] => {
  const result: MenuSortRequest[] = [];

  nodes.forEach((node, index) => {
    result.push({
      menuId: node.menuId,
      parentId: parentId,
      orderNum: index + 1,
      menuName: node.menuName,
      menuType: node.menuType,
      children: node.children ? buildSortData(node.children, node.menuId) : []
    });
  });

  return result;
};

/**
 * 重置排序
 */
const handleReset = async () => {
  try {
    await proxy?.$modal.confirm('确认要重置所有更改吗？此操作不可撤销。');

    resetLoading.value = true;
    await loadTreeData();
    proxy?.$modal.msgSuccess('重置成功');
  } catch (error) {
    if (error !== 'cancel') {
    }
  } finally {
    resetLoading.value = false;
  }
};

/**
 * 取消操作
 */
const handleCancel = () => {
  if (hasChanges.value) {
    proxy?.$modal.confirm('您有未保存的更改，确定要关闭吗？')
      .then(() => {
        visibleProxy.value = false;
      })
      .catch(() => {
        // 用户取消
      });
  } else {
    visibleProxy.value = false;
  }
};

/**
 * 抽屉关闭处理
 */
const handleDrawerClose = () => {
  resetState();
};

/**
 * 获取菜单类型标签
 */
const getMenuTypeTag = (type: string): string => {
  switch (type) {
    case 'M': return 'primary';
    case 'C': return 'success';
    case 'F': return 'warning';
    default: return 'info';
  }
};

/**
 * 获取菜单类型名称
 */
const getMenuTypeName = (type: string): string => {
  switch (type) {
    case 'M': return '目录';
    case 'C': return '菜单';
    case 'F': return '按钮';
    default: return '未知';
  }
};

// ==================== 生命周期钩子 ====================
onMounted(() => {
  // 监听窗口大小变化
  window.addEventListener('resize', handleResize);

  // 初始化容器高度
  setTimeout(() => {
    calculateContainerHeight();
  }, 500);
});

onUnmounted(() => {
  window.removeEventListener('resize', handleResize);
});
</script>

<style scoped>
/* ========== 抽屉基础样式 ========== */
.menu-sort-drawer :deep(.el-drawer__body) {
  padding: 0;
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden; /* 防止抽屉本身出现滚动条 */
}

.drawer-header {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 0 20px;
}

.drawer-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  color: #303133;
}

.title-icon {
  font-size: 20px;
  color: #409eff;
}

.header-description {
  font-size: 14px;
  color: #909399;
  margin: 0;
}

/* ========== 抽屉内容样式 ========== */
.drawer-content {
  flex: 1;
  padding: 20px;
  overflow: hidden; /* 改为hidden，让子容器处理滚动 */
  display: flex;
  flex-direction: column;
  min-height: 0; /* 重要：允许flex子项收缩 */
}

/* ========== 提示区域样式 ========== */
.tips-content {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 16px; /* 确保与树容器有适当间距 */
}

.tips-content span {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
}

/* ========== 排序树样式 ========== */
.sort-tree-card {
  flex: 1; /* 改为flex: 1，让它占据剩余空间 */
  display: flex;
  flex-direction: column;
  min-height: 0; /* 重要：允许flex子项收缩 */
  max-height: calc(100vh - 400px); /* 设置最大高度，确保不会超出视窗 */
}

/* 确保卡片内容区域可以滚动 */
.sort-tree-card :deep(.el-card__body) {
  flex: 1;
  overflow: hidden;
  padding: 20px; /* 恢复原有padding */
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.sort-tree-container {
  flex: 1;
  overflow-y: auto; /* 明确指定垂直滚动 */
  overflow-x: hidden; /* 隐藏水平滚动 */
  padding: 10px 0;
  min-height: 0; /* 重要：允许容器收缩 */
  max-height: 100%; /* 确保不超出父容器 */
  position: relative;
  z-index: 1;
}

.sort-tree {
  background: transparent;
}

.custom-tree-node {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 8px 12px;
  border-radius: 6px;
  transition: all 0.3s ease;
}

.custom-tree-node:hover {
  background-color: #f5f7fa;
  transform: translateX(2px);
}

.node-content {
  display: flex;
  align-items: center;
  flex: 1;
}

.node-icon {
  margin-right: 12px;
}

.type-icon {
  font-size: 16px;
}

.type-icon.directory {
  color: #409eff;
}

.type-icon.menu {
  color: #67c23a;
}

.type-icon.button {
  color: #e6a23c;
}

.node-info {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 8px;
}

.menu-name {
  font-weight: 500;
  color: #303133;
  font-size: 14px;
  flex: 1;
}

.type-tag {
  font-size: 10px;
  padding: 0 4px;
  height: 18px;
  line-height: 18px;
}

.drag-indicator {
  opacity: 0.5;
  transition: opacity 0.3s ease;
}

.custom-tree-node:hover .drag-indicator {
  opacity: 1;
}

/* ========== 卡片头部样式 ========== */
.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
}

.header-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
}

.header-controls {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.tree-stats {
  display: flex;
  align-items: center;
}

.tree-actions {
  display: flex;
  align-items: center;
}

/* ========== 抽屉底部样式 ========== */
.drawer-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  padding: 20px;
  border-top: 1px solid #ebeef5;
  background: #fafafa;
}

/* ========== 拖拽效果样式 ========== */
:deep(.el-tree-node.is-drop-inner > .el-tree-node__content) {
  background-color: #409eff !important;
  color: white;
}

:deep(.el-tree-node__content) {
  padding: 4px 8px;
  border-radius: 4px;
  transition: all 0.3s ease;
}

:deep(.el-tree-node__content:hover) {
  background-color: #f5f7fa;
}

/* ========== 滚动条样式 ========== */
.sort-tree-container::-webkit-scrollbar {
  width: 8px; /* 稍微增加宽度，更容易看到 */
}

.sort-tree-container::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 4px;
}

.sort-tree-container::-webkit-scrollbar-thumb {
  background: #c1c1c1;
  border-radius: 4px;
  transition: background 0.3s ease;
}

.sort-tree-container::-webkit-scrollbar-thumb:hover {
  background: #a8a8a8;
}

/* 为Firefox添加滚动条样式 */
.sort-tree-container {
  scrollbar-width: thin;
  scrollbar-color: #c1c1c1 #f1f1f1;
}

.drawer-content::-webkit-scrollbar {
  width: 6px;
}

.drawer-content::-webkit-scrollbar-thumb {
  background: #c1c1c1;
  border-radius: 3px;
}

.drawer-content::-webkit-scrollbar-thumb:hover {
  background: #a8a8a8;
}

/* ========== 响应式适配 ========== */
@media (max-width: 1200px) {
  .card-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
  }

  .header-controls {
    width: 100%;
    justify-content: space-between;
  }

  .type-tag {
    display: none;
  }

  .sort-tree-card {
    max-height: calc(100vh - 350px); /* 小屏幕上给更多空间给其他元素 */
  }
}

@media (max-width: 768px) {
  .sort-tree-card {
    max-height: calc(100vh - 300px);
  }

  .drawer-content {
    padding: 15px;
  }
}

/* ========== 确保在加载状态下也能正确显示 ========== */
.sort-tree-container[v-loading] {
  min-height: 200px; /* 加载时保持最小高度 */
}
</style>
