<script setup>
import { ref, computed, watch } from 'vue'
// 组件名与模块 id 一致，供 <KeepAlive :include> 按 id 精确匹配；
// 白板后端失活时把它从 include 移除即可卸载组件
defineOptions({ name: 'whiteboard' })
import { useRoute, useRouter } from 'vue-router'
import { appConfig, healthUrl } from '../../config/app.config.js'
import { useLocale } from '../../composables/useLocale.js'
import { getLiveness } from '../../composables/useLiveness.js'
import PageShell from '../../components/ui/PageShell.vue'

const { t } = useLocale()
const route = useRoute()
const router = useRouter()

const wbConfig = appConfig.whiteboard

// 当前白板 id：优先取路由参数 /whiteboard/:boardId，否则用配置默认值
function resolveBoardId(val) {
  const id = String(val ?? '').trim()
  // 仅允许白板服务接受的字符（与后端正则一致：字母数字 _ -），否则回退默认
  return /^[a-zA-Z0-9_-]+$/.test(id) ? id : wbConfig.defaultBoardId
}

const currentBoardId = ref(resolveBoardId(route.params.boardId))
const inputId = ref(currentBoardId.value)

// 路由参数变化时（如浏览器前进/后退、直链进入）同步到当前白板与输入框
watch(
  () => route.params.boardId,
  (val) => {
    const id = resolveBoardId(val)
    if (id !== currentBoardId.value) {
      currentBoardId.value = id
      inputId.value = id
    }
  }
)

// 提交输入框：切换白板并更新 URL（replace，避免历史栈堆积）
function submitBoard() {
  const id = resolveBoardId(inputId.value)
  inputId.value = id
  if (id !== currentBoardId.value) {
    currentBoardId.value = id
    router.replace(`/whiteboard/${encodeURIComponent(id)}`)
  }
}

// 完整白板页 URL（公开，可被 iframe 嵌入）；随 currentBoardId 响应式变化
const boardSrc = computed(
  () => `${wbConfig.baseUrl}${wbConfig.pagePath(currentBoardId.value)}`
)

// 存活态：服务挂掉时显示降级提示（页签本身也已隐藏，但用户若直链进入仍可见）
const aliveState = getLiveness(healthUrl('whiteboard'))
const isDown = computed(() => aliveState.value === 'down')

const loaded = ref(false)
const failed = ref(false)

// 切换白板时重置加载态
watch(boardSrc, () => {
  loaded.value = false
  failed.value = false
  scheduleFailCheck()
})

function onLoad() {
  loaded.value = true
}
function scheduleFailCheck() {
  setTimeout(() => {
    if (!loaded.value) failed.value = true
  }, 6000)
}
scheduleFailCheck()

function openExternal() {
  window.open(boardSrc.value, '_blank', 'noopener')
}
</script>

<template>
  <PageShell title-key="tabs.whiteboard">
    <template #actions>
      <form class="wb-switch" @submit.prevent="submitBoard">
        <label class="wb-switch__label" for="boardInput">
          {{ t('whiteboard.boardId') }}
        </label>
        <input
          id="boardInput"
          v-model="inputId"
          class="wb-switch__input"
          type="text"
          :placeholder="wbConfig.defaultBoardId"
          spellcheck="false"
          autocomplete="off"
          autocapitalize="off"
        />
        <button type="submit" class="wb-switch__go">
          {{ t('whiteboard.switch') }}
        </button>
      </form>
    </template>

    <!-- 服务不可达 / iframe 加载超时降级 -->
    <div v-if="isDown || failed" class="wb-fallback">
      <p class="wb-fallback__text">{{ t('common.serviceUnavailable') }}</p>
      <button type="button" class="wb-fallback__open" @click="openExternal">
        {{ t('whiteboard.openExternal') }}
      </button>
    </div>

    <div v-else class="wb-frame">
      <!-- 加载骨架（iframe 加载完成后淡出） -->
      <Transition name="fade">
        <div v-if="!loaded" class="wb-frame__skeleton">
          <div class="wb-frame__skeleton-text">{{ t('common.loading') }}</div>
        </div>
      </Transition>
      <iframe
        :src="boardSrc"
        class="wb-frame__iframe"
        frameborder="0"
        :title="t('tabs.whiteboard')"
        @load="onLoad"
      />
    </div>
  </PageShell>
</template>

<style scoped>
.wb-switch {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
}
.wb-switch__label {
  font-size: 0.85rem;
  color: var(--text-secondary);
}
.wb-switch__input {
  width: 160px;
  padding: 6px 10px;
  font-size: 0.9rem;
  font-family: var(--font-mono);
  color: var(--text-primary);
  background: var(--bg);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  transition: border-color var(--transition);
}
.wb-switch__input:focus {
  outline: none;
  border-color: var(--accent);
}
.wb-switch__go {
  padding: 7px 14px;
  font-size: 0.85rem;
  font-weight: 500;
  color: #fff;
  background: var(--accent);
  border-radius: var(--radius-sm);
  transition: background var(--transition);
}
.wb-switch__go:hover {
  background: var(--accent-hover);
}
.wb-frame {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
  border: 1px solid var(--border);
  width: 100%;
  /* 记事本以编辑为主，给足高度 */
  height: 70vh;
  min-height: 480px;
  background: var(--surface);
}
.wb-frame__iframe {
  width: 100%;
  height: 100%;
  display: block;
  border: 0;
}
.wb-frame__skeleton {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface);
}
.wb-frame__skeleton-text {
  color: var(--text-tertiary);
  font-size: 0.95rem;
}
.wb-fallback {
  text-align: center;
  padding: var(--space-2xl) var(--space-lg);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface);
}
.wb-fallback__text {
  color: var(--text-secondary);
  margin-bottom: var(--space-md);
}
.wb-fallback__open {
  display: inline-flex;
  align-items: center;
  padding: 8px 18px;
  font-size: 0.9rem;
  font-weight: 500;
  color: #fff;
  background: var(--accent);
  border-radius: var(--radius-sm);
  transition: background var(--transition);
}
.wb-fallback__open:hover {
  background: var(--accent-hover);
}
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.4s ease;
}
.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

@media (max-width: 768px) {
  .wb-switch__input {
    width: 120px;
  }
  .wb-frame {
    height: 65vh;
    min-height: 360px;
  }
}
</style>
