import { defineStore } from 'pinia'
import { ref } from 'vue'
import type { RouteRecordRaw } from 'vue-router'
import type { MenuItem } from '@/types/menu'
import { getRoutes as apiGetRoutes } from '@/api'
import { flattenMenuToRoutes } from '@/utils/routeHelper'

export const usePermissionStore = defineStore('permission', () => {
  /** 用于 Sidebar 渲染的嵌套菜单数据（保持原始层级结构，不含按钮） */
  const menuList = ref<MenuItem[]>([])

  /** 当前用户的按钮权限标识列表，如 ['sys:user:add', 'sys:user:edit'] */
  const permissions = ref<string[]>([])

  /** 标记：动态路由是否已加载完毕 */
  const isRoutesLoaded = ref(false)

  /** 从菜单树中递归收集所有 type=2 的 permission */
  function extractPermissions(menus: MenuItem[]): string[] {
    const perms: string[] = []
    for (const item of menus) {
      if (item.type === 2 && item.permission) {
        perms.push(item.permission)
      }
      if (item.children?.length) {
        perms.push(...extractPermissions(item.children))
      }
    }
    return perms
  }

  /** 过滤掉按钮节点后的菜单树，给 Sidebar 用 */
  function filterButtonsFromMenu(menus: MenuItem[]): MenuItem[] {
    return menus
      .filter((item) => item.type !== 2)
      .map((item) => ({
        ...item,
        children: item.children ? filterButtonsFromMenu(item.children) : [],
      }))
  }

  /**
   * 核心函数：
   * 1. 从 Mock/后端拉取当前用户有权限的路由
   * 2. 提取按钮权限标识
   * 3. 更新 menuList（供 Sidebar 使用，不含按钮）
   * 4. 返回扁平化的路由配置（由路由守卫负责注册到 router）
   */
  async function generateRoutes(token: string): Promise<RouteRecordRaw[]> {
    const res = await apiGetRoutes(token)
    const rawMenuData: MenuItem[] = res.data

    // ① 提取按钮权限
    permissions.value = extractPermissions(rawMenuData)

    // ② 过滤按钮后存给 Sidebar
    menuList.value = filterButtonsFromMenu(rawMenuData)

    // ③ 生成路由
    const flatRoutes = flattenMenuToRoutes(rawMenuData)

    isRoutesLoaded.value = true
    return flatRoutes
  }

  /** 登出时重置（配合页面刷新使用） */
  function reset() {
    menuList.value = []
    permissions.value = []
    isRoutesLoaded.value = false
  }

  return { menuList, permissions, isRoutesLoaded, generateRoutes, reset }
})
