<template>
  <view class="layout-root">
    <view v-if="!isAuthReady" class="auth-loading-overlay" style="flex: 1; display: flex; align-items: center; justify-content: center; height: 100vh; background-color: #f5f5f5;">
      <text style="color: #666; font-size: 16px;">身份鉴权中...</text>
    </view>
    <template v-else>
    <!-- 统一遮罩层 (复刻 CRMEB: 用于所有 Overlay 状态) -->
    <view 
      class="mobile-mask" 
      :class="{ 'mask-show': isOverlayVisible || (isMobile && isMobileMenuOpen) }"
      @click="closeAllMenu"
    ></view>

    <!-- 主侧边栏 (CRMEB风格: 70px) -->
    <AdminAside
      class="admin-sidebar"
      :class="{ 'mobile-aside-open': isMobileMenuOpen }"
      :collapsed="false" 
      :topMenus="topMenus"
      :activeTopMenuId="activeTopMenuId"
      @toggle="toggleMainAsideCollapse"
      @menu-click="onTopMenuClick"
      :asideWidth="ASIDE_W"
    ></AdminAside>

    <!-- 二级侧边栏 (1:1 复刻 CRMEB 抽屉/Dock 平滑切换) -->
    <AdminSubSider
      :visible="isSubSiderVisible"
      :isOverlay="isOverlayVisible || layoutMode === 'mobile'"
      :layoutMode="layoutMode"
      :menuTitle="activeTopMenuTitle"
      :menuTree="activeMenuTree"
      :activeId="activeRouteId"
      :currentPath="currentRoutePath"
      :asideWidth="layoutMode === 'mobile' ? 0 : ASIDE_W"
      :width="SUB_W"
      @sub-click="onSubClick"
    ></AdminSubSider>

    <!-- 右侧内容区 -->
    <view
      class="main"
      :style="{ marginLeft: isMobile ? '0' : mainLeft }"
    >
      <!-- 顶部导航栏 -->
      <AdminHeader
        :breadcrumb="breadcrumb"
        :hasNotification="hasNotification"
        :isMobile="isMobile"
        @search="onSearch"
        @refresh="onRefresh"
        @notify="onNotify"
      ></AdminHeader>

      <!-- 标签页 (CRMEB风格) - 移动端可以隐藏或滚动 -->
      <AdminTagsView
        v-if="!isMobile"
        :tabs="tabs"
        :activeTabId="activeRouteId"
        @tab-click="onTabClick"
        @tab-close="onTabClose"
        @close-other="onCloseOther"
        @close-all="onCloseAll"
        @refresh="onRefresh"
      ></AdminTagsView>

      <!-- 内容展示区 (内部路由渲染) -->
      <view class="content-scroll">
        <view class="content-inner" :class="{ 'is-mobile': isMobile }">
          <slot v-if="hasAccess"></slot>
          <!-- currentPage 为空字符串说明是顶层路由容器，才允许渲染动态组件；
               若 currentPage 非空，说明是子页面自己套了 AdminLayout（作为布局壳使用），
               此时不再渲染 currentComponent，避免递归挂载导致重复请求。 -->
          <!-- #ifdef H5 -->
          <component :is="currentComponent" v-if="hasAccess && !isPageLoading && currentComponent != null && props.currentPage === ''"></component>
          <!-- #endif -->
          <AdminPageLoading v-if="isPageLoading"></AdminPageLoading>
        </view>
        <AdminFooter></AdminFooter>
      </view>
    </view>
    </template>
  </view>
</template>

<script setup lang="uts">
import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
import AdminAside from '@/layouts/admin/components/AdminAside.uvue'
import AdminSubSider from '@/layouts/admin/components/AdminSubSider.uvue'
import AdminHeader from '@/layouts/admin/components/AdminHeader.uvue'
import AdminTagsView from '@/layouts/admin/components/AdminTagsView.uvue'
import AdminFooter from '@/layouts/admin/components/AdminFooter.uvue'
import AdminPageLoading from '@/layouts/admin/components/AdminPageLoading.uvue'

import { 
  getTopMenus, 
  getGroupsByTopMenu, 
  getRoutesByGroup,
  findRouteById,
  getBreadcrumb
} from '@/layouts/admin/router/adminRoutes.uts'
import type { TopMenu, MenuGroup, RouteRecord } from '@/layouts/admin/router/adminRoutes.uts'

import { MenuNode, settingSubSiderMenu } from '@/layouts/admin/router/settingSubSiderMenu.uts'

import {
  activeTopMenuId,
  activeRouteId,
  lastSubIdByMenu,
  tabs,
  isMainAsideCollapsed,
  showSubSider,
  windowWidth,
  layoutMode,
  isMobile,
  isMobileMenuOpen,
  isOverlayVisible,
  openRoute,
  closeTab,
  closeOtherTabs,
  closeAllTabs,
  toggleMainAsideCollapse as storeToggleCollapse,
  toggleSubSider as storeToggleSubSider,
  initNavState,
  restoreNavState
} from '@/layouts/admin/store/adminNavStore.uts'
import type { TabItem } from '@/layouts/admin/store/adminNavStore.uts'

import { getComponent } from '@/layouts/admin/router/adminComponentMap.uts'
import { hasAdminModuleAccess } from '@/layouts/admin/utils/role.uts'
import { ensureAdminSession, handleSessionExpired } from '@/layouts/admin/utils/adminAuth.uts'

const props = defineProps({
  currentPage: {
    type: String,
    default: ''
  }
})

// 侧边栏宽度配置 (CRMEB 1:1)
const ASIDE_W = 70    
const SUB_W = 200     

// 页面加载状态
const isPageLoading = ref(false)
const isAuthReady = ref(false)

const hasAccess = computed<boolean>(() => {
  
  
  return hasAdminModuleAccess(activeTopMenuId.value)
})

const hasNotification = ref<boolean>(false)

/**
 * 核心逻辑：计算二级菜单是否应该以 Overlay (抽屉) 模式展示
 * CRMEB 规则：Tablet 屏 (768~1199) 为 Overlay
 */
const isSubSiderOverlay = computed<boolean>(() => {
  return layoutMode.value === 'tablet'
})

// 当前路由的路径
const currentRoutePath = computed<string>(() => {
  const route = findRouteById(activeRouteId.value)
  return route ? route.path : ''
})

// 将旧的 Group + Routes 转换为新的 Tree 结构 (支持 3 级嵌套)
const activeMenuTree = computed<MenuNode[]>(() => {
  if (activeTopMenuId.value === 'setting') {
    return settingSubSiderMenu
  }
  
  const tree: MenuNode[] = []
  activeGroups.value.forEach(group => {
    const routes = activeRoutes.value.get(group.id)
    if (routes != null && routes.length > 0) {
      const children: MenuNode[] = []
      routes.forEach(route => {
        children.push({
          id: route.id,
          title: route.title,
          type: 'page',
          path: route.path
        } as MenuNode)
      })
      
      // 1:1 复刻 CRMEB: 如果分组标题为空，直接将子菜单平铺在顶层，不渲染分组行
      if (group.title === '') {
        children.forEach(child => {
          tree.push(child)
        })
      } else {
        tree.push({
          id: group.id,
          title: group.title,
          type: 'group',
          children: children
        } as MenuNode)
      }
    }
  })
  
  return tree
})

/**
 * 核心逻辑：二级菜单是否可见
 * 1. 如果有子菜单内容 (activeMenuTree > 0)
 * 2. 如果是 Desktop 且 showSubSider 为真 (Dock模式)
 * 3. 如果是 Tablet/Mobile 且 isOverlayVisible 为真 (Overlay模式)
 */
const isSubSiderVisible = computed<boolean>(() => {
  // 首页模块通常不显示 SubSider
  if (activeTopMenuId.value === 'home' || activeMenuTree.value.length === 0) return false
  
  if (layoutMode.value === 'desktop') {
    return showSubSider.value
  }
  
  // Tablet 和 Mobile 模式下，直接由 isOverlayVisible 控制
  return isOverlayVisible.value
})

/**
 * 核心逻辑：计算主内容区左偏移量 (mainLeft)
 * 严格按照断点策略计算，防止遮挡
 * 1. Desktop: ASIDE_W + (SUB_W if dock)
 * 2. Tablet: ASIDE_W (sub-sider 是 overlay，不占位)
 * 3. Mobile: 0
 */
const mainLeft = computed<string>(() => {
  if (layoutMode.value === 'mobile') {
    return '0px'
  }
  
  let left = ASIDE_W // 只要不是 Mobile，主侧栏 70px 始终 Dock
  
  // 只有在 Desktop 模式且二级菜单处于 Dock 模式显示时，才累加宽度
  if (layoutMode.value === 'desktop' && showSubSider.value && activeMenuTree.value.length > 0) {
    left += SUB_W
  }
  
  return left + 'px'
})

// 获取一级菜单列表
const topMenus = computed<TopMenu[]>(() => {
  return getTopMenus()
})

// 当前选中一级菜单的标题
const activeTopMenuTitle = computed<string>(() => {
  const menu = topMenus.value.find(m => m.id === activeTopMenuId.value)
  return menu ? menu.title : ''
})

// 当前一级菜单的分组列表
const activeGroups = computed<MenuGroup[]>(() => {
  return getGroupsByTopMenu(activeTopMenuId.value)
})

// 当前一级菜单的所有路由
const activeRoutes = computed<Map<string, RouteRecord[]>>(() => {
  const result = new Map<string, RouteRecord[]>()
  activeGroups.value.forEach(group => {
    result.set(group.id, getRoutesByGroup(group.id))
  })
  return result
})

// 面包屑导航
const breadcrumb = computed<Array<{id: string, title: string}>>(() => {
  return getBreadcrumb(activeRouteId.value)
})

// 当前渲染的组件
const currentComponent = computed<any>(() => {
  
  
  const route = findRouteById(activeRouteId.value)
  if (!route) return null
  return getComponent(route.componentKey)
})

// 监听路由变化，同步状态 (处理从 Tabs 或外部跳转的情况)
watch(() => activeRouteId.value, (newId) => {
  // 触发页面加载动画
  isPageLoading.value = true
  setTimeout(() => {
    isPageLoading.value = false
  }, 400) // 给予足够的时间让异步组件加载
  
  const route = findRouteById(newId)
  if (route && route.parentId) {
    // 同步一级菜单
    if (activeTopMenuId.value !== route.parentId) {
      activeTopMenuId.value = route.parentId
    }
    // 同步最后访问记录
    lastSubIdByMenu.value[route.parentId] = newId
    
    // 如果是 Desktop 且 SubSider 关着，自动打开（除非用户手动关了）
    if (layoutMode.value === 'desktop' && !showSubSider.value) {
      showSubSider.value = true
    }
  }
}, { immediate: true })

// ============================================
// 事件处理
// ============================================

function onTopMenuClick(menu: TopMenu): void {
  activeTopMenuId.value = menu.id
  
  // 1:1 复刻 CRMEB 交互：点击 Aside 立即展示 SubSider
  if (layoutMode.value === 'desktop') {
    showSubSider.value = true
  } else {
    isOverlayVisible.value = true
    isMobileMenuOpen.value = false // 如果主侧栏开着，关掉它，开二级
  }

  // 1:1 复刻 CRMEB 交互：点击一级菜单后，自动跳转到上一次记录的子页面或第一个子页面
  let targetId = lastSubIdByMenu.value[menu.id]
  if (!targetId && activeMenuTree.value.length > 0) {
    const firstNode = activeMenuTree.value[0]
    if (firstNode.type === 'page') {
      targetId = firstNode.id
    } else if (firstNode.children != null && firstNode.children!.length > 0) {
      targetId = firstNode.children![0].id
    }
  }

  if (targetId) {
    openRoute(targetId)
  } else {
    // 兜底逻辑：如果没有二级菜单，跳转到 index
    openRoute(menu.id + '_index')
  }
}

function onSubClick(payload: { id: string, path: string }): void {
  // CRMEB 跳转逻辑
  openRoute(payload.id)
  
  // 更新最后访问记录
  lastSubIdByMenu.value[activeTopMenuId.value] = payload.id
  
  // 重要：1:1 复刻 CRMEB，点击二级菜单项后，SubSider 通常保持显示状态
  // 只有在 Mobile 模式下，用户如果是想“跳转并收起”，通常需要点击遮罩或关闭按钮，但这里我们按桌面版常驻逻辑
  // 如果需要移动端点击自动关闭，才解开下面注释
  // if (layoutMode.value === 'mobile') {
  //   closeAllMenu()
  // }
}

function onTabClick(tab: TabItem): void {
  openRoute(tab.id, false)
}

function onTabClose(tabId: string): void {
  closeTab(tabId)
}

function onCloseOther(tabId: string): void {
  closeOtherTabs(tabId)
}

function onCloseAll(): void {
  closeAllTabs()
}

function toggleMainAsideCollapse(): void {
  storeToggleCollapse()
}

function closeAllMenu(): void {
  isMobileMenuOpen.value = false
  isOverlayVisible.value = false
  // 注意：在 Desktop 模式下，closeAllMenu 通常不隐藏 showSubSider，除非用户手动点汉堡按钮
}

function onSearch(): void {
  uni.showToast({ title: '搜索', icon: 'none' })
}

function onRefresh(): void {
  uni.showToast({ title: '刷新', icon: 'none' })
}

function onNotify(): void {
  uni.showToast({ title: '通知', icon: 'none' })
}

// ============================================
// 生命周期
// ============================================

let resizeTid: any = null

onMounted(async () => {
  // 挂载鉴权相关的事件监听器，并在首次进入时阻断认证
  try {
    const isOk = await ensureAdminSession()
    if (!isOk) {
       return // 鉴权失败内部已处理跳转，终止后续挂载
    }
  } catch (e) {
    handleSessionExpired()
    return
  }
  
  uni.$on('AUTH_SESSION_EXPIRED', () => { handleSessionExpired() })

  // 增加 visibilitychange 监听：在用户电脑休眠或者长时间放置重新激活时，核验会话
  // #ifdef H5
  if (typeof window !== 'undefined') {
      window.addEventListener('visibilitychange', handleVisibilityChange)
  }
  // #endif

  isAuthReady.value = true

  // 第二段：尝试从 sessionStorage 恢复上次打开的页签状态
  // restoreNavState 会校验路由有效性和权限，过滤无效项后重建 tabs
  const restored = restoreNavState()
  if (!restored) {
    // 首次打开 / 缓存为空 / 恢复失败 → 走默认初始化（只有首页tab）
    initNavState()
    if (props.currentPage != '') {
      openRoute(props.currentPage as string)
    }
  }
  // restored=true 时，activeRouteId 已由 restoreNavState 正确设置，无需额外跳转
  
  // 初始化窗口宽度
  windowWidth.value = uni.getWindowInfo().windowWidth
  
  // 监听窗口变化 (增加节流保护与跨断点状态重置)
  uni.onWindowResize((res) => {
    if (resizeTid != null) {
      cancelAnimationFrame(resizeTid)
    }
    
    resizeTid = requestAnimationFrame(() => {
      const oldMode = layoutMode.value
      windowWidth.value = res.size.windowWidth
      const newMode = layoutMode.value
      
      // 跨断点自动关闭所有 Overlay，防止状态残留遮挡内容
      if (oldMode != newMode) {
        isOverlayVisible.value = false
        isMobileMenuOpen.value = false
        // 如果切到桌面端，默认展开二级侧栏以符合 CRMEB 习惯
        if (newMode === 'desktop') {
          showSubSider.value = true
        }
      }
      
      resizeTid = null
    })
  })
})

// ===== Auth State Handlers ===== 
let _lastVisibilityCheck = 0
const handleVisibilityChange = async () => {
    // #ifdef H5
    if (document.visibilityState === 'visible') {
        const now = Date.now()
        // 节流机制，防止频繁切换标签页产生过多校验
        if (now - _lastVisibilityCheck < 10000) return
        _lastVisibilityCheck = now
        
        // 简易验证即可，如果底层 token 已经失效而 fetch 拿不到，就会报出 401 触发全局 AUTH_SESSION_EXPIRED
        try {
            await ensureAdminSession()
        } catch(e) {}
    }
    // #endif
}

onUnmounted(() => {
  uni.$off('AUTH_SESSION_EXPIRED')
  // #ifdef H5
  if (typeof window !== 'undefined') {
      window.removeEventListener('visibilitychange', handleVisibilityChange)
  }
  // #endif
})

</script>

<style scoped lang="scss">
.layout-root {
  --admin-page-padding-desktop: 20px;
  --admin-page-padding-mobile: 10px;
  --admin-section-gap: 20px;
  --admin-card-padding: 24px;

  display: flex;
  flex-direction: row;
  width: 100%;
  min-height: 100vh;
  background: #f5f7f9;
  position: relative;
}

/* 移动端侧边栏样式 */
.mobile-aside {
  position: absolute;
  left: -70px; /* 隐藏在左侧，匹配 ASIDE_W: 70 */
  top: 0;
  bottom: 0;
  z-index: 1001;
  transition: transform 0.3s ease;
  background: #fff;
}

.mobile-aside-open {
  transform: translateX(70px); /* 移入视图 */
}

.mobile-mask {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.4);
  z-index: 1000;
  opacity: 0;
  visibility: hidden;
  transition: opacity 300ms ease, visibility 0s linear 300ms;
}

.mask-show {
  opacity: 1;
  visibility: visible;
  transition: opacity 300ms ease, visibility 0s linear 0s;
}

.main {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  transition: margin-left 300ms ease;
  background: #f5f7f9;
  width: 100%;
}

/* 响应式强制覆盖 */
@media screen and (max-width: 768px) {
  .main {
    margin-left: 0 !important;
  }

  /* 强行改变侧边栏布局模式 */
  .admin-sidebar {
    position: absolute !important;
    left: -70px !important; /* 隐藏在左侧 */
    top: 0;
    bottom: 0;
    z-index: 1001;
    transition: transform 0.3s ease !important;
  }

  /* 展开时的状态 */
  .mobile-aside-open {
    transform: translateX(70px) !important;
  }
}

.content-scroll {
  flex: 1;
  overflow-y: scroll;
  overflow-x: auto; /* 允许横向滚动，兼容极端窄屏 */
  background: #f5f7f9;
  padding: 0;
}

.content-inner {
  min-height: calc(100vh - 120px);
  padding: var(--admin-page-padding-desktop);
  display: flex;
  flex-direction: column;
}

.content-inner.is-mobile {
  padding: var(--admin-page-padding-mobile);
}
</style>
