<script setup lang="ts">
import { ref, watch, nextTick } from 'vue'
import { useBookmarkStore } from '@/stores/bookmark'
import type { Bookmark } from '@/types'

const props = defineProps<{
  visible: boolean
}>()

const emit = defineEmits<{
  'update:visible': [value: boolean]
  close: []
}>()

const bookmarkStore = useBookmarkStore()

const keyword = ref('')
const results = ref<Bookmark[]>([])
const loading = ref(false)
const selectedIndex = ref(0)
const inputRef = ref<HTMLInputElement>()

watch(() => props.visible, (val) => {
  if (val) {
    nextTick(() => {
      inputRef.value?.focus()
    })
  } else {
    keyword.value = ''
    results.value = []
    selectedIndex.value = 0
  }
})

let searchTimer: number | null = null

function handleInput() {
  if (searchTimer) {
    clearTimeout(searchTimer)
  }

  if (!keyword.value.trim()) {
    results.value = []
    return
  }

  loading.value = true
  searchTimer = window.setTimeout(async () => {
    await bookmarkStore.searchBookmarks(keyword.value)
    results.value = bookmarkStore.searchResults
    selectedIndex.value = 0
    loading.value = false
  }, 300)
}

function handleKeydown(e: KeyboardEvent) {
  switch (e.key) {
    case 'ArrowDown':
      e.preventDefault()
      if (selectedIndex.value < results.value.length - 1) {
        selectedIndex.value++
      }
      break
    case 'ArrowUp':
      e.preventDefault()
      if (selectedIndex.value > 0) {
        selectedIndex.value--
      }
      break
    case 'Enter':
      e.preventDefault()
      if (results.value[selectedIndex.value]) {
        handleSelect(results.value[selectedIndex.value])
      }
      break
    case 'Escape':
      handleClose()
      break
  }
}

function handleSelect(bookmark: Bookmark) {
  bookmarkStore.recordVisit(bookmark.id)
  window.open(bookmark.url, '_blank')
  handleClose()
}

function handleClose() {
  emit('update:visible', false)
  emit('close')
  bookmarkStore.clearSearch()
}
</script>

<template>
  <Teleport to="body">
    <Transition name="fade">
      <div v-if="visible" class="search-overlay" @click.self="handleClose">
        <div class="search-modal">
          <div class="search-header">
            <el-icon class="search-icon"><Search /></el-icon>
            <input
              ref="inputRef"
              v-model="keyword"
              type="text"
              class="search-input"
              placeholder="搜索书签..."
              @input="handleInput"
              @keydown="handleKeydown"
            />
            <kbd class="search-kbd" @click="handleClose">ESC</kbd>
          </div>

          <div class="search-body">
            <div v-if="loading" class="search-loading">
              <el-icon class="is-loading"><Loading /></el-icon>
              搜索中...
            </div>

            <div v-else-if="keyword && results.length === 0" class="search-empty">
              未找到相关书签
            </div>

            <div v-else-if="results.length > 0" class="search-results">
              <div
                v-for="(item, index) in results"
                :key="item.id"
                class="search-item"
                :class="{ active: index === selectedIndex }"
                @click="handleSelect(item)"
                @mouseenter="selectedIndex = index"
              >
                <img
                  v-if="item.icon"
                  :src="item.icon"
                  class="favicon"
                  @error="($event.target as HTMLImageElement).style.display = 'none'"
                />
                <span v-else class="favicon-placeholder">{{ item.title[0] }}</span>
                <div class="item-content">
                  <div class="item-title">{{ item.title }}</div>
                  <div class="item-url">{{ item.url }}</div>
                </div>
                <div class="item-tags">
                  <el-tag
                    v-for="tag in item.tags.slice(0, 2)"
                    :key="tag"
                    size="small"
                    type="info"
                  >
                    {{ tag }}
                  </el-tag>
                </div>
              </div>
            </div>

            <div v-else class="search-hint">
              输入关键词搜索书签
            </div>
          </div>

          <div class="search-footer">
            <span><kbd>↑</kbd><kbd>↓</kbd> 导航</span>
            <span><kbd>Enter</kbd> 打开</span>
            <span><kbd>ESC</kbd> 关闭</span>
          </div>
        </div>
      </div>
    </Transition>
  </Teleport>
</template>

<style lang="scss" scoped>
.search-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 100px;
  z-index: 2000;
  backdrop-filter: blur(4px);
}

.search-modal {
  width: 600px;
  max-width: 90vw;
  background: #fff;
  border-radius: 16px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
  overflow: hidden;
}

.search-header {
  display: flex;
  align-items: center;
  padding: 16px 20px;
  border-bottom: 1px solid #eee;

  .search-icon {
    font-size: 20px;
    color: #999;
    margin-right: 12px;
  }

  .search-input {
    flex: 1;
    border: none;
    outline: none;
    font-size: 16px;
    background: transparent;

    &::placeholder {
      color: #999;
    }
  }

  .search-kbd {
    background: #f0f0f0;
    padding: 4px 8px;
    border-radius: 4px;
    font-size: 12px;
    color: #666;
    cursor: pointer;

    &:hover {
      background: #e0e0e0;
    }
  }
}

.search-body {
  max-height: 400px;
  overflow-y: auto;
  padding: 8px;
}

.search-loading,
.search-empty,
.search-hint {
  padding: 40px;
  text-align: center;
  color: #999;
}

.search-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

.search-results {
  .search-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 16px;
    border-radius: 8px;
    cursor: pointer;
    transition: background 0.2s;

    &:hover,
    &.active {
      background: #f5f5f5;
    }

    .favicon {
      width: 24px;
      height: 24px;
      border-radius: 4px;
      flex-shrink: 0;
    }

    .favicon-placeholder {
      width: 24px;
      height: 24px;
      border-radius: 4px;
      background: linear-gradient(135deg, #667eea, #764ba2);
      color: #fff;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 12px;
      font-weight: 600;
      flex-shrink: 0;
    }

    .item-content {
      flex: 1;
      min-width: 0;

      .item-title {
        font-weight: 500;
        color: #333;
        margin-bottom: 4px;
      }

      .item-url {
        font-size: 12px;
        color: #999;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
    }

    .item-tags {
      display: flex;
      gap: 4px;
    }
  }
}

.search-footer {
  display: flex;
  justify-content: center;
  gap: 24px;
  padding: 12px;
  border-top: 1px solid #eee;
  background: #fafafa;
  font-size: 12px;
  color: #999;

  kbd {
    background: #e0e0e0;
    padding: 2px 6px;
    border-radius: 4px;
    margin-right: 4px;
  }
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.2s ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}
</style>

