<template>
  <ChunkErrorBoundary>
    <ElConfigProvider size="default" :locale="locales[language]" :z-index="3000">
      <RouterView></RouterView>
    </ElConfigProvider>
  </ChunkErrorBoundary>
</template>

<script setup lang="ts">
  import { useUserStore } from './store/modules/user'
  import zh from 'element-plus/es/locale/lang/zh-cn'
  import en from 'element-plus/es/locale/lang/en'
  import { systemUpgrade } from '@/utils'
  import { AuthService } from '@/api/modules'
  import { ApiStatus } from './utils/http/status'
  import { setThemeTransitionClass } from '@/utils'
  import { checkStorageCompatibility } from '@/utils'
  import ChunkErrorBoundary from '@/components/core/others/ChunkErrorBoundary.vue'
  import { ElMessageBox } from 'element-plus'

  const userStore = useUserStore()
  const { language } = storeToRefs(userStore)

  const locales = {
    zh: zh,
    en: en
  }

  const VERSION_CHECK_INTERVAL = 5 * 60 * 1000
  const VERSION_PROMPT_STORAGE_KEY = 'admin-xm-iot:confirmed-version-update'
  let versionCheckTimer: number | undefined
  let currentEntrySignature = ''
  let upgradePromptVisible = false
  let removeVisibilityChangeListener: (() => void) | undefined

  onBeforeMount(() => {
    setThemeTransitionClass(true)
  })

  onMounted(() => {
    // 检查存储兼容性
    checkStorageCompatibility()
    // 提升暗黑主题下页面刷新视觉体验
    setThemeTransitionClass(false)
    // 系统升级
    systemUpgrade()
    // 检查前端版本更新
    startVersionUpdateCheck()
    // 获取用户信息
    getUserInfo()
  })

  onBeforeUnmount(() => {
    if (versionCheckTimer) {
      window.clearInterval(versionCheckTimer)
    }
    removeVisibilityChangeListener?.()
  })

  // 获取用户信息
  const getUserInfo = async () => {
    if (userStore.isLogin && userStore.accessToken) {
      try {
        const res = await AuthService.getUserInfo()
        if (res.code === ApiStatus.success && res.data) {
          // API 返回的是 { user, permissions }，我们需要保存 user 和 permissions
          userStore.setUserInfo(res.data.user)
          userStore.setPermissions(res.data.permissions || [])
        }
      } catch (error) {
        console.error('获取用户信息失败:', error)
      }
    }
  }

  const getEntrySignature = (html: string) => {
    const matches = html.match(/(?:src|href)="[^"]*\/assets\/[^""]+\.(?:js|css)"/g)
    return matches?.sort().join('|') || ''
  }

  const getLoadedEntrySignature = () => {
    return Array.from(
      document.querySelectorAll<HTMLScriptElement | HTMLLinkElement>('script[src],link[href]')
    )
      .map((element) => ('src' in element ? element.src : element.href))
      .filter((url) => /\/assets\/.*\.(js|css)(\?|$)/.test(url))
      .sort()
      .join('|')
  }

  const getStringHash = (value: string) => {
    let hash = 0

    for (let i = 0; i < value.length; i++) {
      hash = (hash << 5) - hash + value.charCodeAt(i)
      hash |= 0
    }

    return Math.abs(hash).toString(36)
  }

  const getBrowserFingerprint = () => {
    return getStringHash(
      [
        navigator.userAgent,
        navigator.language,
        navigator.platform,
        Intl.DateTimeFormat().resolvedOptions().timeZone,
        `${screen.width}x${screen.height}x${screen.colorDepth}`
      ].join('|')
    )
  }

  const getConfirmedVersionKey = (signature: string) => {
    return `${getBrowserFingerprint()}:${getStringHash(signature)}`
  }

  const getConfirmedVersionUpdate = () => {
    try {
      return localStorage.getItem(VERSION_PROMPT_STORAGE_KEY)
    } catch {
      return null
    }
  }

  const setConfirmedVersionUpdate = (signature: string) => {
    try {
      localStorage.setItem(VERSION_PROMPT_STORAGE_KEY, getConfirmedVersionKey(signature))
    } catch {
      // localStorage may be unavailable in private mode.
    }
  }

  const reloadWithCacheBuster = () => {
    const url = new URL(window.location.href)
    url.searchParams.set('_t', Date.now().toString())
    window.location.replace(url.toString())
  }

  const checkVersionUpdate = async () => {
    if (upgradePromptVisible || document.hidden) return

    try {
      const response = await fetch(import.meta.env.BASE_URL, {
        cache: 'no-store'
      })
      const html = await response.text()
      const latestSignature = getEntrySignature(html)

      if (!latestSignature) return

      if (!currentEntrySignature) {
        currentEntrySignature = latestSignature
        return
      }

      if (currentEntrySignature !== latestSignature) {
        if (getConfirmedVersionUpdate() === getConfirmedVersionKey(latestSignature)) {
          currentEntrySignature = latestSignature
          return
        }

        upgradePromptVisible = true
        await ElMessageBox.alert('系统已发布新版本，请刷新页面后继续使用。', '发现新版本', {
          confirmButtonText: '立即更新',
          type: 'warning',
          closeOnClickModal: false,
          closeOnPressEscape: false
        })
        setConfirmedVersionUpdate(latestSignature)
        currentEntrySignature = latestSignature
        reloadWithCacheBuster()
      }
    } catch (error) {
      console.warn('检查版本更新失败:', error)
    } finally {
      upgradePromptVisible = false
    }
  }

  const startVersionUpdateCheck = () => {
    if (import.meta.env.DEV) return

    currentEntrySignature = getLoadedEntrySignature()
    checkVersionUpdate()
    versionCheckTimer = window.setInterval(checkVersionUpdate, VERSION_CHECK_INTERVAL)
    const handleVisibilityChange = () => {
      if (!document.hidden) {
        checkVersionUpdate()
      }
    }
    document.addEventListener('visibilitychange', handleVisibilityChange)
    removeVisibilityChangeListener = () => {
      document.removeEventListener('visibilitychange', handleVisibilityChange)
    }
  }
</script>
