<template>
  <div class="page-container">
    <el-card>
      <template #header>
        <div class="card-header">
          <span>菜单管理</span>
          <el-button type="primary" v-permission="'menu:create'" @click="handleAdd">
            <el-icon><Plus /></el-icon>新增菜单
          </el-button>
        </div>
      </template>
      
      <el-table
        :data="menuTree"
        row-key="id"
        :tree-props="{ children: 'children' }"
        v-loading="loading"
      >
        <el-table-column prop="name" label="菜单名称" min-width="180" />
        <el-table-column prop="icon" label="图标" width="80">
          <template #default="{ row }">
            <el-icon v-if="row.icon"><component :is="row.icon" /></el-icon>
          </template>
        </el-table-column>
        <el-table-column prop="path" label="路由路径" min-width="150" />
        <el-table-column prop="component" label="组件路径" min-width="180" />
        <el-table-column prop="permission" label="权限标识" min-width="120" />
        <el-table-column prop="menuType" label="类型" width="80">
          <template #default="{ row }">
            <el-tag :type="menuTypeMap[row.menuType]?.type">
              {{ menuTypeMap[row.menuType]?.label }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="sortOrder" label="排序" width="80" />
        <el-table-column prop="status" label="状态" width="80">
          <template #default="{ row }">
            <el-tag :type="row.status === 1 ? 'success' : 'danger'">
              {{ row.status === 1 ? '显示' : '隐藏' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="200" fixed="right">
          <template #default="{ row }">
            <el-button link type="primary" v-permission="'menu:update'" @click="handleEdit(row)">编辑</el-button>
            <el-button link type="primary" v-permission="'menu:create'" @click="handleAddChild(row)">添加子菜单</el-button>
            <el-button link type="danger" v-permission="'menu:delete'" @click="handleDelete(row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-card>

    <!-- 新增/编辑对话框 -->
    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="550px" @close="resetForm">
      <el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px">
        <el-form-item label="上级菜单" prop="parentId">
          <el-tree-select
            v-model="formData.parentId"
            :data="menuTreeForSelect"
            :props="{ label: 'name', value: 'id', children: 'children' }"
            check-strictly
            :render-after-expand="false"
            placeholder="请选择上级菜单"
            clearable
            style="width: 100%"
          />
        </el-form-item>
        <el-form-item label="菜单类型" prop="menuType">
          <el-radio-group v-model="formData.menuType">
            <el-radio :value="1">目录</el-radio>
            <el-radio :value="2">菜单</el-radio>
            <el-radio :value="3">按钮</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="菜单名称" prop="name">
          <el-input v-model="formData.name" placeholder="请输入菜单名称" />
        </el-form-item>
        <!-- 目录和菜单显示图标 -->
        <el-form-item v-if="formData.menuType !== 3" label="图标" prop="icon">
          <el-input v-model="formData.icon" placeholder="请输入图标名称，如 Setting" />
        </el-form-item>
        <!-- 菜单类型显示路由路径和组件路径 -->
        <el-form-item v-if="formData.menuType === 2" label="路由路径" prop="path">
          <el-input v-model="formData.path" placeholder="请输入路由路径，如 /system/menu" />
        </el-form-item>
        <el-form-item v-if="formData.menuType === 2" label="组件路径" prop="component">
          <el-input v-model="formData.component" placeholder="请输入组件路径，如 system/menu/index" />
        </el-form-item>
        <!-- 按钮类型显示权限标识 -->
        <el-form-item v-if="formData.menuType === 3" label="权限标识" prop="permission">
          <el-input v-model="formData.permission" placeholder="请输入权限标识，如 menu:create" />
        </el-form-item>
        <el-form-item label="排序" prop="sortOrder">
          <el-input-number v-model="formData.sortOrder" :min="0" :max="9999" />
        </el-form-item>
        <el-form-item label="状态" prop="status">
          <el-radio-group v-model="formData.status">
            <el-radio :value="1">显示</el-radio>
            <el-radio :value="0">隐藏</el-radio>
          </el-radio-group>
        </el-form-item>
        <!-- 菜单类型显示外链和缓存选项 -->
        <el-form-item v-if="formData.menuType === 2" label="是否外链" prop="isExternal">
          <el-switch v-model="formData.isExternal" />
        </el-form-item>
        <el-form-item v-if="formData.menuType === 2" label="是否缓存" prop="isCache">
          <el-switch v-model="formData.isCache" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="handleSubmit" :loading="submitLoading">确定</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue'
import { Plus } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus'
import { getMenuTree, createMenu, updateMenu, deleteMenu, type MenuTree, type CreateMenuRequest, type UpdateMenuRequest } from '@/api/menu'

const loading = ref(false)
const menuTree = ref<MenuTree[]>([])

const menuTypeMap: Record<number, { label: string; type: string }> = {
  1: { label: '目录', type: 'info' },
  2: { label: '菜单', type: '' },
  3: { label: '按钮', type: 'warning' }
}

// 表单相关状态
const dialogVisible = ref(false)
const isEdit = ref(false)
const dialogTitle = computed(() => isEdit.value ? '编辑菜单' : '新增菜单')
const formRef = ref<FormInstance>()
const submitLoading = ref(false)

// 表单数据
const formData = reactive({
  id: 0,
  parentId: 0,
  name: '',
  path: '',
  component: '',
  icon: '',
  menuType: 2,
  permission: '',
  sortOrder: 0,
  status: 1,
  isExternal: false,
  isCache: true
})

// 用于选择父菜单的树（编辑时排除当前菜单及其子菜单）
const menuTreeForSelect = computed(() => {
  if (!isEdit.value) {
    return [{ id: 0, name: '顶级菜单', children: menuTree.value }]
  }
  // 编辑时过滤掉自己及子菜单
  const filterTree = (nodes: MenuTree[]): MenuTree[] => {
    return nodes
      .filter(n => n.id !== formData.id)
      .map(n => ({ ...n, children: filterTree(n.children || []) }))
  }
  return [{ id: 0, name: '顶级菜单', children: filterTree(menuTree.value) }]
})

// 表单验证规则
const formRules: FormRules = {
  name: [{ required: true, message: '请输入菜单名称', trigger: 'blur' }],
  menuType: [{ required: true, message: '请选择菜单类型', trigger: 'change' }],
  path: [{
    validator: (_rule, value, callback) => {
      if (formData.menuType === 2 && !value) {
        callback(new Error('菜单类型必须填写路由路径'))
      } else if (value && !formData.isExternal && !value.startsWith('/')) {
        callback(new Error('内部路由路径必须以 / 开头'))
      } else {
        callback()
      }
    },
    trigger: 'blur'
  }],
  component: [{
    validator: (_rule, value, callback) => {
      if (formData.menuType === 2 && !value) {
        callback(new Error('菜单类型必须填写组件路径'))
      } else {
        callback()
      }
    },
    trigger: 'blur'
  }],
  permission: [{
    validator: (_rule, value, callback) => {
      if (formData.menuType === 3 && !value) {
        callback(new Error('按钮类型必须填写权限标识'))
      } else {
        callback()
      }
    },
    trigger: 'blur'
  }],
  sortOrder: [{ 
    type: 'number', 
    min: 0, 
    message: '排序值必须为非负整数', 
    trigger: 'blur' 
  }]
}

// 重置表单
const resetForm = () => {
  formData.id = 0
  formData.parentId = 0
  formData.name = ''
  formData.path = ''
  formData.component = ''
  formData.icon = ''
  formData.menuType = 2
  formData.permission = ''
  formData.sortOrder = 0
  formData.status = 1
  formData.isExternal = false
  formData.isCache = true
  formRef.value?.resetFields()
}

// 提交表单
const handleSubmit = async () => {
  const valid = await formRef.value?.validate()
  if (!valid) return

  submitLoading.value = true
  try {
    const requestData: CreateMenuRequest | UpdateMenuRequest = {
      parentId: formData.parentId,
      name: formData.name,
      path: formData.path || undefined,
      component: formData.component || undefined,
      icon: formData.icon || undefined,
      menuType: formData.menuType,
      permission: formData.permission || undefined,
      sortOrder: formData.sortOrder,
      status: formData.status,
      isExternal: formData.isExternal,
      isCache: formData.isCache
    }

    if (isEdit.value) {
      await updateMenu(formData.id, requestData)
      ElMessage.success('更新成功')
    } else {
      await createMenu(requestData)
      ElMessage.success('创建成功')
    }
    dialogVisible.value = false
    fetchData()
  } catch (error: any) {
    ElMessage.error(error.message || '操作失败')
  } finally {
    submitLoading.value = false
  }
}

const fetchData = async () => {
  loading.value = true
  try {
    const res = await getMenuTree()
    menuTree.value = res.data
  } finally {
    loading.value = false
  }
}

// 新增菜单
const handleAdd = () => {
  resetForm()
  isEdit.value = false
  dialogVisible.value = true
}

// 添加子菜单
const handleAddChild = (row: MenuTree) => {
  resetForm()
  isEdit.value = false
  formData.parentId = row.id
  dialogVisible.value = true
}

// 编辑菜单
const handleEdit = (row: MenuTree) => {
  resetForm()
  isEdit.value = true
  // 填充表单数据
  formData.id = row.id
  formData.parentId = row.parentId
  formData.name = row.name
  formData.path = row.path || ''
  formData.component = row.component || ''
  formData.icon = row.icon || ''
  formData.menuType = row.menuType
  formData.permission = row.permission || ''
  formData.sortOrder = row.sortOrder
  formData.status = row.status
  formData.isExternal = row.isExternal
  formData.isCache = row.isCache
  dialogVisible.value = true
}

const handleDelete = async (row: MenuTree) => {
  // 构建确认消息，如果有子菜单则警告
  const hasChildren = row.children && row.children.length > 0
  const confirmMessage = hasChildren
    ? `菜单 "${row.name}" 下有 ${row.children.length} 个子菜单，删除后子菜单也将被删除。确定要删除吗？`
    : `确定要删除菜单 "${row.name}" 吗？`

  try {
    await ElMessageBox.confirm(confirmMessage, '删除确认', {
      type: 'warning',
      confirmButtonText: '确定删除',
      cancelButtonText: '取消'
    })
    
    // 调用删除 API
    await deleteMenu(row.id)
    ElMessage.success('删除成功')
    // 刷新数据
    fetchData()
  } catch (error: any) {
    // 用户取消删除时 error 为 'cancel'
    if (error !== 'cancel') {
      ElMessage.error(error.message || '删除失败')
    }
  }
}

onMounted(() => {
  fetchData()
})
</script>

<style scoped>
.page-container {
  padding: 0;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
</style>
