<script lang="ts" setup>
import type { MenuEntity } from '@vben/types';

import { computed, onMounted, ref } from 'vue';

import { VbenTree } from '@vben/common-ui';

import { ElButton, ElDialog, ElInput, ElTag } from 'element-plus';

import { getMenuListApi } from '#/api/menu';

// 扩展菜单类型，添加children属性
interface MenuTreeNode extends MenuEntity {
  children?: MenuTreeNode[];
}

interface Props {
  /** 当前选中的权限ID字符串，以逗号分隔 */
  modelValue?: string;
  /** 是否禁用 */
  disabled?: boolean;
  /** 占位符文本 */
  placeholder?: string;
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: '',
  disabled: false,
  placeholder: '请选择权限',
});

const emit = defineEmits<{
  'update:modelValue': [value: string];
}>();

const treeData = ref<MenuTreeNode[]>([]);
const loading = ref(false);
const dialogVisible = ref(false);
const treeRef = ref();

// 临时选中的权限（用于弹窗中的操作）
const tempSelectedPermissions = ref<number[]>([]);

// 将字符串转换为数组
const selectedPermissions = computed({
  get() {
    return tempSelectedPermissions.value;
  },
  set(value: number[]) {
    tempSelectedPermissions.value = value;
  },
});

// 显示文本
const displayText = computed(() => {
  if (!props.modelValue) return '';
  const count = props.modelValue.split(',').filter((id) => id.trim()).length;
  return count > 0 ? `已选择 ${count} 项权限` : '';
});

// 选中数量
const selectedCount = computed(() => {
  return tempSelectedPermissions.value.length;
});

// 获取菜单类型标签样式
function getMenuTypeTag(type: number) {
  const typeMap = {
    1: { text: '目录', type: 'primary' },
    2: { text: '菜单', type: 'success' },
    3: { text: '按钮', type: 'warning' },
    4: { text: 'API接口', type: 'info' },
  } as const;
  return (
    typeMap[type as keyof typeof typeMap] || { text: '未知', type: 'info' }
  );
}

// 将平铺的菜单数据转换为树形结构
function buildMenuTree(menus: MenuEntity[]): MenuTreeNode[] {
  const menuMap = new Map<number, MenuTreeNode>();
  const rootMenus: MenuTreeNode[] = [];

  // 先创建所有节点的映射
  menus.forEach((menu) => {
    menuMap.set(menu.menu_id, { ...menu, children: [] });
  });

  // 构建树形结构
  menus.forEach((menu) => {
    const menuNode = menuMap.get(menu.menu_id)!;
    if (menu.parent_id === 0) {
      // 根节点
      rootMenus.push(menuNode);
    } else {
      // 子节点
      const parent = menuMap.get(menu.parent_id);
      if (parent) {
        parent.children = parent.children || [];
        parent.children.push(menuNode);
      }
    }
  });

  // 递归排序
  function sortTree(nodes: MenuTreeNode[]): MenuTreeNode[] {
    return nodes
      .sort((a, b) => (a.order_num || 0) - (b.order_num || 0))
      .map((node) => {
        if (node.children && node.children.length > 0) {
          node.children = sortTree(node.children);
        }
        return node;
      });
  }

  return sortTree(rootMenus);
}

// 获取菜单列表
async function fetchMenuList() {
  try {
    loading.value = true;
    const res = await getMenuListApi({
      pageindex: 1,
      rows: 10_000, // 获取所有菜单
    });

    if (res && res.Data) {
      treeData.value = buildMenuTree(res.Data);
    }
  } catch (error) {
    console.error('获取菜单列表失败', error);
  } finally {
    loading.value = false;
  }
}

// 获取所有菜单ID
function getAllMenuIds(): number[] {
  const ids: number[] = [];
  function traverse(nodes: MenuTreeNode[]) {
    nodes.forEach((node) => {
      ids.push(node.menu_id);
      if (node.children && node.children.length > 0) {
        traverse(node.children);
      }
    });
  }
  traverse(treeData.value);
  return ids;
}

// 打开弹窗
function openDialog() {
  if (props.disabled) return;

  // 初始化临时选中状态
  tempSelectedPermissions.value = props.modelValue
    ? props.modelValue
        .split(',')
        .map(Number)
        .filter((id) => !Number.isNaN(id))
    : [];

  dialogVisible.value = true;

  // 如果还没有加载菜单数据，则加载
  if (treeData.value.length === 0) {
    fetchMenuList();
  }
}

// 确认选择
function confirmDialog() {
  const stringValue = tempSelectedPermissions.value.join(',');
  emit('update:modelValue', stringValue);
  dialogVisible.value = false;
}

// 取消选择
function cancelDialog() {
  dialogVisible.value = false;
  // 恢复原始选中状态
  tempSelectedPermissions.value = props.modelValue
    ? props.modelValue
        .split(',')
        .map(Number)
        .filter((id) => !Number.isNaN(id))
    : [];
}

// 全选
function selectAll() {
  tempSelectedPermissions.value = getAllMenuIds();
}

// 清空
function clearAll() {
  tempSelectedPermissions.value = [];
}

// 展开全部
function expandAll() {
  if (treeRef.value && treeRef.value.expandAll) {
    treeRef.value.expandAll();
  }
}

// 收起全部
function collapseAll() {
  if (treeRef.value && treeRef.value.collapseAll) {
    treeRef.value.collapseAll();
  }
}

onMounted(() => {
  // 组件挂载时不立即加载数据，等用户点击时再加载
});
</script>

<template>
  <div class="permission-tree-wrapper">
    <!-- 触发按钮 -->
    <div class="permission-trigger" @click="openDialog">
      <ElInput
        :model-value="displayText"
        readonly
        :placeholder="placeholder"
        class="cursor-pointer"
      >
        <template #suffix>
          <span class="cursor-pointer text-gray-400 hover:text-gray-600">
            ⚙️
          </span>
        </template>
      </ElInput>
    </div>

    <!-- 权限选择弹窗 -->
    <ElDialog
      v-model="dialogVisible"
      title="权限设置"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      :append-to-body="true"
    >
      <div class="permission-dialog-content">
        <!-- 操作栏 -->
        <div class="permission-actions mb-4">
          <div class="flex items-center justify-between">
            <div class="flex items-center gap-2">
              <ElButton size="small" @click="selectAll">全选</ElButton>
              <ElButton size="small" @click="clearAll">清空</ElButton>
              <ElButton size="small" @click="expandAll">展开全部</ElButton>
              <ElButton size="small" @click="collapseAll">收起全部</ElButton>
            </div>
            <div class="text-sm text-gray-500">
              已选择: {{ selectedCount }} 项
            </div>
          </div>
        </div>

        <!-- 权限树 -->
        <div class="permission-tree-container">
          <VbenTree
            ref="treeRef"
            v-model="selectedPermissions"
            :tree-data="treeData"
            :multiple="true"
            :check-strictly="true"
            :default-expanded-level="2"
            label-field="remark"
            value-field="menu_id"
            children-field="children"
            :bordered="true"
            class="permission-tree"
          >
            <template #node="{ value }">
              <div class="flex items-center gap-2">
                <span class="text-sm">{{
                  `${value.menu_id}_${value.remark || value.menu_name}`
                }}</span>
                <ElTag
                  v-if="value.menu_type"
                  :type="getMenuTypeTag(value.menu_type).type"
                  size="small"
                  effect="light"
                >
                  {{ getMenuTypeTag(value.menu_type).text }}
                </ElTag>
              </div>
            </template>
          </VbenTree>
        </div>

        <!-- 加载状态 -->
        <div v-if="loading" class="flex items-center justify-center py-8">
          <span class="text-sm text-gray-500">加载中...</span>
        </div>
      </div>

      <template #footer>
        <div class="dialog-footer">
          <ElButton @click="cancelDialog">取消</ElButton>
          <ElButton type="primary" @click="confirmDialog">确定</ElButton>
        </div>
      </template>
    </ElDialog>
  </div>
</template>

<style scoped>
.permission-tree-wrapper {
  width: 100%;
}

.permission-trigger :deep(.el-input__wrapper) {
  cursor: pointer;
}

.permission-trigger :deep(.el-input__inner) {
  cursor: pointer;
}

.permission-dialog-content {
  display: flex;
  flex-direction: column;
  height: 100%; /* 使用父容器的全部高度 */
}

.permission-tree-container {
  flex: 1;
  min-height: 0; /* 确保flex子元素可以收缩 */
  max-height: 80vh; /* 最大高度不超过80vh */
  padding: 8px;
  overflow: hidden;
  background-color: #fff;
  border: 1px solid #d9d9d9;
  border-radius: 6px;
}

.permission-tree-container :deep(.tree-node) {
  padding: 4px 8px;
  border-radius: 4px;
  transition: background-color 0.2s;
}

.permission-tree-container :deep(.tree-node:hover) {
  background-color: #f5f5f5;
}

.permission-tree {
  height: 100%;
  max-height: calc(80vh - 100px); /* 减去容器padding和其他元素高度 */
  overflow: hidden auto; /* 隐藏x轴滚动 */ /* 设置为y轴滚动 */
}

/* 确保弹窗内容区域正确布局 */
:deep(.el-dialog__body) {
  height: calc(100vh - 140px); /* 减去头部(60px)和底部(80px)的高度 */
  padding: 20px;
  overflow: hidden;
}

:deep(.el-dialog__footer) {
  flex-shrink: 0; /* 防止底部按钮被压缩 */
  padding: 15px 20px;
  border-top: 1px solid #e4e7ed;
}
</style>
