<!-- =====================================================================
  LibraryModal.vue — 演示文库弹窗
  ===================================================================== -->
<script setup lang="ts">
import { ref, computed, watch, onMounted, onUnmounted } from 'vue'
import type { LibItem, Slide } from '../../core/types'
import { store, resolveBg } from '../../core/store'
import { appPrompt, appConfirm } from '../../core/dialog'
import ElementView from '../editor/ElementView.vue'
import Icon from '../common/Icon.vue'

const props = defineProps<{ visible: boolean }>()
const emit = defineEmits<{
  (e: 'close'): void
  (e: 'toast', msg: string): void
  (e: 'switch-tab', tab: string): void
  (e: 'open-deck'): void
}>()

const libVersion = ref(0)
const nameInput = ref('')
const opsOpenId = ref<string | null>(null)

function toggleOps(id: string) {
  opsOpenId.value = opsOpenId.value === id ? null : id
}

function onDocClick(e: MouseEvent) {
  const t = e.target as HTMLElement
  if (!t.closest('.lib-ops')) opsOpenId.value = null
}
onMounted(() => document.addEventListener('mousedown', onDocClick))
onUnmounted(() => document.removeEventListener('mousedown', onDocClick))

/** 读文库列表（非响应式，靠 libVersion 触发重算） */
const library = computed<LibItem[]>(() => {
  void libVersion.value
  return store.getLibrary()
})
const activeId = computed(() => {
  void libVersion.value
  return store.getActiveLibId()
})

const libCount = computed(() => library.value.length)
const placeholder = computed(() => {
  const cur = library.value.find(x => x.id === activeId.value)
  return cur
    ? '当前：「' + cur.name + '」，留空同名覆盖，输入新名另存为新份'
    : '为当前演示命名后存入文库…'
})

function bump() { libVersion.value++ }

watch(() => props.visible, (v) => {
  if (v) { bump(); nameInput.value = '' }
})

function toast(msg: string) { emit('toast', msg) }

function firstSlide(item: LibItem): Slide | null {
  const s = item?.deck?.slides
  return s && s.length ? s[0] : null
}

function formatTime(ts: number): string {
  if (!ts) return ''
  const diff = Date.now() - ts
  if (diff < 60000) return '刚刚'
  if (diff < 3600000) return Math.floor(diff / 60000) + ' 分钟前'
  if (diff < 86400000) return Math.floor(diff / 3600000) + ' 小时前'
  const d = new Date(ts)
  return (d.getMonth() + 1) + '月' + d.getDate() + '日'
}

function onNameKeydown(e: KeyboardEvent) {
  if (e.key === 'Enter') { e.preventDefault(); onSave() }
}

function onSave() {
  const name = nameInput.value.trim()
  if (!name && !store.getActiveLibId()) {
    toast('请输入名称')
    return
  }
  store.saveToLibrary(name || null)
  toast(name ? ('已存入文库：' + name) : '已更新到文库')
  nameInput.value = ''
  bump()
}

function onNewBlank() {
  store.newBlankDeck()
  emit('switch-tab', 'props')
  emit('open-deck')
  toast('已新建空白演示，在右侧添加元素')
  emit('close')
}

function onOpen(id: string) {
  if (store.loadFromLibrary(id)) {
    opsOpenId.value = null
    toast('已打开')
    emit('open-deck')
    emit('close')
  }
}

async function onRename(id: string) {
  const cur = store.getLibrary().find(x => x.id === id)
  const name = await appPrompt('重命名', { defaultValue: cur ? cur.name : '' })
  opsOpenId.value = null
  if (name != null && name.trim()) {
    store.renameInLibrary(id, name.trim())
    bump()
  }
}

function onDuplicate(id: string) {
  opsOpenId.value = null
  store.duplicateInLibrary(id)
  toast('已复制')
  bump()
}

async function onDelete(id: string) {
  opsOpenId.value = null
  if (await appConfirm('删除这份演示？', '此操作不可撤销', { danger: true, okText: '删除' })) {
    store.deleteFromLibrary(id)
    toast('已删除')
    bump()
  }
}
</script>

<template>
  <div class="modal-mask lib-modal-mask" :class="{ hidden: !visible }" @click.self="emit('close')">
    <div class="modal lib-modal">
      <div class="lib-head">
        <h3>演示文库</h3>
        <button class="btn ghost" @click="onNewBlank">＋ 新建空白</button>
      </div>
      <p class="modal-tip">保存多套演示文稿到本地，随时切换。</p>

      <div class="lib-save-card">
        <div class="lib-save-title">
          <span><Icon name="save" :size="14" /> 保存当前演示</span>
          <span v-if="activeId" class="lib-autosave-flag">改动已自动同步到文库</span>
        </div>
        <div class="lib-save-row">
          <input type="text" v-model="nameInput" :placeholder="placeholder" @keydown="onNameKeydown" />
          <button class="btn primary" @click="onSave">存入文库</button>
        </div>
      </div>

      <div class="lib-hint">共 {{ libCount }} 份</div>

      <div class="lib-list">
        <div v-for="it in library" :key="it.id" class="lib-item" :class="{ active: it.id === activeId }" :data-id="it.id">
          <div class="lib-thumb" :style="{ background: firstSlide(it) ? resolveBg(firstSlide(it)!.background) : '#fff' }">
            <div v-if="firstSlide(it)" style="position:absolute;top:0;left:0;width:1280px;height:720px;transform:scale(0.05625);transform-origin:top left;pointer-events:none">
              <ElementView v-for="el in firstSlide(it)!.elements" :key="el.id" :el="el" :bg="firstSlide(it)!.background" />
            </div>
          </div>
          <div class="lib-info">
            <div class="lib-name">{{ it.name }}<span v-if="it.id === activeId">  (当前)</span></div>
            <div class="lib-meta">{{ (it.deck && it.deck.slides ? it.deck.slides.length : 0) + ' 页 · ' + formatTime(it.updatedAt || it.createdAt) }}</div>
          </div>
          <div class="lib-ops">
            <button class="btn primary small" @click="onOpen(it.id)">打开</button>
            <button class="btn" @click="toggleOps(it.id)">⋯</button>
            <div v-if="opsOpenId === it.id" class="ops-menu">
              <button @click="onRename(it.id)">重命名</button>
              <button @click="onDuplicate(it.id)">复制</button>
              <button class="danger" @click="onDelete(it.id)">删除</button>
            </div>
          </div>
        </div>
      </div>

      <div class="modal-actions">
        <button class="btn" @click="emit('close')">关闭</button>
      </div>
    </div>
  </div>
</template>

<style scoped>
.lib-head { display: flex; align-items: center; justify-content: space-between; }
.lib-head h3 { margin: 0; }
.lib-save-card {
  border: 1px solid color-mix(in srgb, var(--ui-primary, #5b5bd6) 22%, transparent);
  background: color-mix(in srgb, var(--ui-primary, #5b5bd6) 5%, #fff);
  border-radius: 10px;
  padding: 12px 14px;
  margin-bottom: 12px;
}
.lib-save-title { font-size: 13px; font-weight: 600; color: var(--ui-text, #1e293b); margin-bottom: 8px; display: flex; align-items: center; justify-content: space-between; }
.lib-autosave-flag { font-size: 11px; font-weight: 400; color: var(--ui-muted, #64748b); }
.lib-save-row { display: flex; gap: 8px; }
.lib-save-row input { flex: 1; }
.lib-ops { position: relative; }
.ops-menu {
  position: absolute; right: 0; top: calc(100% + 4px);
  background: #fff; border: 1px solid var(--ui-border, #e2e8f0);
  border-radius: 8px; box-shadow: 0 4px 16px rgba(15,23,42,.12);
  min-width: 96px; z-index: 10; overflow: hidden; padding: 4px 0;
}
.ops-menu button { display: block; width: 100%; text-align: left; padding: 6px 12px; border: none; background: none; font-size: 12px; cursor: pointer; }
.ops-menu button:hover { background: var(--ui-hover, #f1f5f9); }
.ops-menu button.danger { color: var(--ui-danger, #dc2626); }
</style>
