<script setup lang="ts">
import { computed, onMounted, onBeforeUnmount, onErrorCaptured, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import OaAppShell from './oa/OaAppShell.vue'
import OaLogin from './oa/OaLogin.vue'
import ErrorFallback from './components/erp/ErrorFallback.vue'
import { useSession } from './oa/session'
import { OA_AUTH_REQUIRED_EVENT } from './oa/api'

// 独立窗口路由（meta.standalone）整页渲染，不套顶部外壳——复刻致远 window.open 弹窗形态。
const route = useRoute()
const router = useRouter()
const isStandalone = computed(() => route.meta?.standalone === true)

// ----- 全局错误边界 -----
// 子树渲染/生命周期抛出未捕获异常时，捕获并渲染友好降级页，避免整窗白屏。
// 返回 false 阻止异常继续向上冒泡（同时仍由 main.ts errorHandler 记日志+轻提示）。
const renderError = ref<Error | null>(null)
onErrorCaptured((err) => {
  renderError.value = err instanceof Error ? err : new Error(String(err))
  return false
})
// 路由切换后清掉错误态，让用户导航到别的页面可正常恢复。
watch(
  () => route.fullPath,
  () => {
    renderError.value = null
  }
)
function retryRender() {
  renderError.value = null
}
function goHome() {
  renderError.value = null
  void router.push('/')
}

// App 级登录门：启动用已存 token 拉会话；未登录铺登录页，已登录进主壳。
// 任意请求 401 -> 清会话回到登录门。
const session = useSession()

function onAuthRequired() {
  session.clear()
}

onMounted(() => {
  void session.init()
  window.addEventListener(OA_AUTH_REQUIRED_EVENT, onAuthRequired)
})
onBeforeUnmount(() => {
  window.removeEventListener(OA_AUTH_REQUIRED_EVENT, onAuthRequired)
})
</script>

<template>
  <div v-if="!session.ready.value" class="oa-boot" v-loading="true" element-loading-text="加载中…" />
  <OaLogin v-else-if="!session.isAuthed.value" />
  <!-- 独立窗口路由：整页渲染，不套外壳 -->
  <template v-else-if="isStandalone">
    <div v-if="renderError" class="oa-errboundary oa-errboundary--full">
      <ErrorFallback @retry="retryRender" @home="goHome" />
    </div>
    <RouterView v-else />
  </template>
  <OaAppShell v-else>
    <div v-if="renderError" class="oa-errboundary">
      <ErrorFallback @retry="retryRender" @home="goHome" />
    </div>
    <RouterView v-else v-slot="{ Component }">
      <component :is="Component" />
    </RouterView>
  </OaAppShell>
</template>

<style scoped>
.oa-boot {
  position: fixed;
  inset: 0;
}

/* 错误边界容器：壳内场景给一张卡片包住降级页；独立窗口铺满整屏。 */
.oa-errboundary {
  max-width: 1360px;
  margin: 0 auto;
  background: var(--erp-color-surface);
  border: 1px solid var(--erp-color-border-soft);
  border-radius: var(--erp-radius-md);
}

.oa-errboundary--full {
  min-height: 100vh;
  border: 0;
  border-radius: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
</style>
