<template>
  <a-layout class="min-h-screen layout-shell">
    <a-layout class="w-full px-4 py-4">
      <ConsoleHeader
        :user="user"
        :user-display-name="userDisplayName"
        @logout="logout"
      />

      <a-layout class="body">
        <a-layout-sider
          class="sider"
          :width="240"
          breakpoint="lg"
          theme="light"
          :trigger="null"
          collapsible
          v-model:collapsed="collapsed"
        >
          <a-dropdown
            placement="bottomLeft"
            :trigger="['hover']"
            :disabled="tenantOptions.length <= 1"
          >
            <div class="sider-brand" :class="{ collapsed }">
              <a-avatar :size="28">
                <template #icon>
                  <AppstoreOutlined />
                </template>
              </a-avatar>
              <div v-if="!collapsed" class="sider-title">
                控制台
              </div>
            </div>

            <template #overlay>
              <a-menu
                :selected-keys="[String(currentTenantId)]"
                @click="onTenantMenuClick"
              >
                <a-menu-item
                  v-for="t in tenantOptions"
                  :key="String(t.tenantId ?? '')"
                  :disabled="switchingTenant || !t.tenantId"
                >
                  <a-space>
                    <a-avatar
                      :size="20"
                      shape="square"
                      :src="t.logo || t.avatar || t.avatarUrl"
                    >
                      <template v-if="!(t.logo || t.avatar || t.avatarUrl)" #icon>
                        <AppstoreOutlined />
                      </template>
                    </a-avatar>
                    <span class="tenant-menu-title">
                      {{ t.tenantName || t.companyName || t.username || `租户 ${t.tenantId}` }}
                    </span>
                  </a-space>
                </a-menu-item>
              </a-menu>
            </template>
          </a-dropdown>

          <a-menu
            mode="inline"
            theme="light"
            :selected-keys="selectedKeys"
            :open-keys="collapsed ? [] : openKeys"
            :inline-collapsed="collapsed"
            @open-change="onOpenChange"
            @click="onMenuClick"
          >
            <template v-for="entry in menu" :key="isGroup(entry) ? entry.key : entry.to">
              <a-sub-menu v-if="isGroup(entry)" :key="entry.key">
                <template v-if="entry.icon" #icon>
                  <component :is="entry.icon" />
                </template>
                <template #title>{{ entry.label }}</template>
                <a-menu-item v-for="item in entry.children" :key="item.to">
                  <template v-if="item.icon" #icon>
                    <component :is="item.icon" />
                  </template>
                  {{ item.label }}
                </a-menu-item>
              </a-sub-menu>
              <a-menu-item v-else :key="entry.to">
                <template v-if="entry.icon" #icon>
                  <component :is="entry.icon" />
                </template>
                {{ entry.label }}
              </a-menu-item>
            </template>
          </a-menu>

          <div
            class="sider-collapse-trigger"
            role="button"
            tabindex="0"
            :aria-label="collapsed ? '展开菜单' : '收起菜单'"
            @click="toggleCollapsed"
            @keydown.enter.prevent="toggleCollapsed"
            @keydown.space.prevent="toggleCollapsed"
          >
            <RightOutlined :style="{fontSize: '10px', paddingRight: '4px'}" v-if="collapsed" />
            <LeftOutlined :style="{fontSize: '10px', paddingRight: '4px'}" v-else />
          </div>

        </a-layout-sider>

        <a-layout class="main">
          <a-layout-content class="content">
            <a-spin v-if="!ready" size="large" tip="加载中..." class="spin" />
            <template v-else>
              <slot />
            </template>
          </a-layout-content>
        </a-layout>
      </a-layout>
    </a-layout>
  </a-layout>
</template>

<script setup lang="ts">
import { message } from 'ant-design-vue'
import { AppstoreOutlined, LeftOutlined, RightOutlined } from '@ant-design/icons-vue'
import { consoleNav, type ConsoleNavEntry, type ConsoleNavGroup, type ConsoleNavItem } from '@/config/console-nav'
import { getTenantInfo, getUserInfo } from '@/api/layout'
import { getSiteInfo } from '@/api/cms/cmsWebsite'
import type { User } from '@/api/system/user/model'
import { listAdminsByPhoneAll } from '@/api/system/user'
import type { Company } from '@/api/system/company/model'
import type { CmsWebsite } from '@/api/cms/cmsWebsite/model'
import { TEMPLATE_ID } from '@/config/setting'
import { getToken, removeToken } from '@/utils/token-util'
import { clearAuthz, setAuthzFromUser } from '@/utils/permission'
import { getTenantId } from '@/utils/domain'

const route = useRoute()
const collapsed = ref(false)
const menu = computed(() => consoleNav)
const user = ref<User | null>(null)
const tenant = ref<Company | null>(null)
const siteInfo = ref<CmsWebsite | null>(null)
const tenantOptions = ref<User[]>([])
const switchingTenant = ref(false)

const currentTenantId = computed(() => {
  const tid = tenant.value?.tenantId ?? user.value?.tenantId
  if (typeof tid === 'number' && Number.isFinite(tid)) return tid
  return Number(getTenantId(String(TEMPLATE_ID)))
})

const currentTenantName = computed(() => {
  // const websiteName = siteInfo.value?.websiteName?.trim()
  // if (websiteName) return websiteName
  return (
    // tenant.value?.shortName?.trim() ||
    // tenant.value?.companyName?.trim() ||
    // tenant.value?.tenantName?.trim() ||
    '小程序'
  )
})

const currentTenantLogo = computed(() => {
  const candidate =
    tenant.value?.companyLogo ||
    'https://mp.websoft.top/logo.png'
  if (typeof candidate !== 'string') return ''
  const normalized = candidate.trim()
  if (!normalized || normalized === 'null' || normalized === 'undefined') return ''
  return normalized
})

const userDisplayName = computed(() => {
  const u = user.value
  const nickname = u?.nickname?.trim()
  const username = u?.username?.trim()
  const phone = u?.phone?.trim()
  const mobile = u?.mobile?.trim()
  if (nickname) return nickname
  if (username) return username
  if (phone) return phone
  if (mobile) return mobile
  return '当前用户'
})

function isGroup(entry: ConsoleNavEntry): entry is ConsoleNavGroup {
  return 'children' in entry
}

function entriesToItems(entries: ConsoleNavEntry[]): ConsoleNavItem[] {
  return entries.flatMap((entry) => {
    if (isGroup(entry)) return entry.children
    return [{ key: entry.key, label: entry.label, to: entry.to }]
  })
}

const selectedKeys = computed(() => {
  const all = entriesToItems(menu.value)
  if (route.path === '/console') return ['/console/tenant/index']
  if (route.path.startsWith('/console/tenant/')) return ['/console/tenant/index']
  const match = all.find((item) => route.path === item.to)
  if (match) return [match.to]
  return []
})

const openKeys = ref<string[]>([])
function syncOpenKeys() {
  const hit = menu.value.find(
    (entry) => isGroup(entry) && entry.children.some((c) => route.path === c.to || route.path.startsWith(c.to + '/'))
  )
  openKeys.value = hit ? [hit.key] : []
}

function toggleCollapsed() {
  collapsed.value = !collapsed.value
}

function onOpenChange(keys: string[]) {
  openKeys.value = Array.isArray(keys) ? keys.slice(-1) : []
}

function onMenuClick(info: { key: string }) {
  navigateTo(String(info.key))
}

function logout() {
  removeToken()
  try {
    localStorage.removeItem('TenantId')
    localStorage.removeItem('UserId')
  } catch {
    // ignore
  }
  clearAuthz()
  navigateTo('/')
}

const ready = ref(false)

watch(
  () => route.path,
  () => syncOpenKeys(),
  { immediate: true }
)

function normalizeTenantOptions(list: User[]) {
  const byTenantId = new Map<number, User>()
  for (const item of list) {
    const tid = item.tenantId
    if (typeof tid !== 'number' || !Number.isFinite(tid)) continue
    if (!byTenantId.has(tid)) byTenantId.set(tid, item)
  }
  const options = Array.from(byTenantId.values())
  options.sort((a, b) => (a.tenantId ?? 0) - (b.tenantId ?? 0))
  return options
}

async function loadTenantOptions(me: User) {
  const phone = me.phone || me.mobile
  if (!phone) {
    tenantOptions.value = me.tenantId ? [{ ...me }] : []
    return
  }

  try {
    const list = await listAdminsByPhoneAll({ phone, templateId: Number(TEMPLATE_ID) })
    const options = normalizeTenantOptions(Array.isArray(list) ? list : [])
    tenantOptions.value = options.length ? options : (me.tenantId ? [{ ...me }] : [])
  } catch {
    tenantOptions.value = me.tenantId ? [{ ...me }] : []
  }
}

async function refreshSessionContext() {
  const me = await getUserInfo()
  user.value = me
  setAuthzFromUser(me)
  await loadTenantOptions(me)
  try {
    siteInfo.value = await getSiteInfo()
  } catch {
    siteInfo.value = null
  }
  try {
    tenant.value = await getTenantInfo()
  } catch {
    tenant.value = null
  }
}

async function switchTenant(tenantId: number) {
  if (!import.meta.client) return
  if (!Number.isFinite(tenantId)) return
  if (tenantId === currentTenantId.value) return

  switchingTenant.value = true
  try {
    const prev = localStorage.getItem('TenantId')
    localStorage.setItem('TenantId', String(tenantId))
    try {
      await refreshSessionContext()
    } catch (e) {
      if (prev) localStorage.setItem('TenantId', prev)
      else localStorage.removeItem('TenantId')
      throw e
    }
    message.success('已切换租户')
  } catch (e: unknown) {
    message.error(e instanceof Error ? e.message : '切换租户失败')
  } finally {
    switchingTenant.value = false
  }
}

function onTenantMenuClick(info: { key: string }) {
  const tid = Number(info.key)
  if (!Number.isFinite(tid)) return
  switchTenant(tid)
}

onMounted(async () => {
  const token = getToken()
  if (!token) {
    clearAuthz()
    message.error('请先登录')
    await navigateTo('/login')
    ready.value = true
    return
  }

  try {
    await refreshSessionContext()
  } catch {
    clearAuthz()
  }

  syncOpenKeys()
  ready.value = true
})
</script>

<style scoped>
.layout-shell {
  background: #f5f5f5;
}

.sider {
  border-radius: 12px;
  overflow: visible;
  position: relative;
  background: #fff;
  border: 1px solid rgba(0, 0, 0, 0.06);
}

.sider-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 16px 16px 10px;
}

.sider-brand.collapsed {
  justify-content: center;
}

.sider-brand.switchable {
  cursor: pointer;
}

.sider-brand.switchable:hover {
  background: rgba(0, 0, 0, 0.03);
}

.sider-title {
  color: rgba(0, 0, 0, 0.88);
  font-size: 16px;
}

.sider-actions {
  padding: 12px;
}

:deep(.ant-menu-inline) {
  border-inline-end: 0;
}

.sider-collapse-trigger {
  position: absolute;
  top: 50%;
  right: -16px;
  width: 16px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  background: #fff;
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-left: 0;
  border-radius: 0 9999px 9999px 0;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.08);
  color: rgba(0, 0, 0, 0.65);
  cursor: pointer;
  z-index: 2;
}

.sider-collapse-trigger:hover {
  background: rgba(0, 0, 0, 0.02);
}

.sider-collapse-trigger:active {
  background: rgba(0, 0, 0, 0.04);
}

.body {
  margin: 16px 0;
}

.main {
  margin-left: 16px;
  background: transparent;
}

.content {
  min-height: 520px;
  background: #fff;
  border-radius: 12px;
  padding: 18px;
}

.spin {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 380px;
}
</style>
