<script setup lang="ts">
import { request } from '~/utils/http/factory'

// ── Types ──

export interface SelectedCard {
  cardId: number
  sortOrder?: number
}

interface ServerCard {
  id: number
  type: string
  title: string
  description: string | null
  images: { id: number; url: string; sortOrder: number }[]
}

// ── Props / Emits ──

const props = defineProps<{
  modelValue: SelectedCard[]
}>()

const emit = defineEmits<{
  'update:modelValue': [value: SelectedCard[]]
}>()

// ── Card search ──

const searchQuery = ref('')
const allCards = ref<ServerCard[]>([])
const loadingCards = ref(false)
const showPicker = ref(false)

// ── Computed ──

const selectedIds = computed(() => new Set(props.modelValue.map((c) => c.cardId)))

const filteredCards = computed(() => {
  const q = searchQuery.value.trim().toLowerCase()
  if (!q) return allCards.value.filter((c) => !selectedIds.value.has(c.id))
  return allCards.value.filter(
    (c) =>
      !selectedIds.value.has(c.id) &&
      (c.title.toLowerCase().includes(q) || c.type.toLowerCase().includes(q)),
  )
})

const selectedCards = computed(() => {
  return props.modelValue
    .map((sc) => {
      const card = allCards.value.find((c) => c.id === sc.cardId)
      return { ...sc, card }
    })
    .filter((s) => s.card != null) as {
    cardId: number
    sortOrder: number
    card: ServerCard
  }[]
})

const cardThumb = (card: ServerCard) => {
  return card.images?.[0]?.url ?? null
}

// ── Actions ──

async function loadCards() {
  if (allCards.value.length > 0) return
  loadingCards.value = true
  try {
    const raw = await request<{ code: number; data: { items: ServerCard[] } }>(
      '/api/cards?pageSize=200',
    )
    allCards.value = raw.data.items
  } catch {
    // silent
  } finally {
    loadingCards.value = false
  }
}

function addCard(card: ServerCard) {
  const next = [...props.modelValue, { cardId: card.id, sortOrder: props.modelValue.length }]
  emit('update:modelValue', next)
  searchQuery.value = ''
}

function removeCard(cardId: number) {
  const filtered = props.modelValue
    .filter((c) => c.cardId !== cardId)
    .map((c, i) => ({ ...c, sortOrder: i }))
  emit('update:modelValue', filtered)
}

function moveCard(cardId: number, dir: -1 | 1) {
  const idx = props.modelValue.findIndex((c) => c.cardId === cardId)
  if (idx === -1) return
  const target = idx + dir
  if (target < 0 || target >= props.modelValue.length) return
  const next = [...props.modelValue]
  const tmp = next[idx]!
  next[idx] = next[target]!
  next[target] = tmp
  // Reassign sort order
  emit(
    'update:modelValue',
    next.map((c, i) => ({ ...c, sortOrder: i })),
  )
}

function onPickerFocus() {
  showPicker.value = true
  loadCards()
}

function onPickerBlur() {
  // Delay to allow click on dropdown items
  setTimeout(() => {
    showPicker.value = false
  }, 200)
}

// ── Init ──

onMounted(() => {
  // Preload cards so selected chips render immediately
  if (props.modelValue.length > 0) {
    loadCards()
  }
})
</script>

<template>
  <div class="card-picker">
    <!-- Selected Cards -->
    <div v-if="selectedCards.length > 0" class="selected-list">
      <div
        v-for="(sc, idx) in selectedCards"
        :key="sc.cardId"
        class="selected-chip"
      >
        <div class="chip-thumb">
          <img v-if="cardThumb(sc.card)" :src="cardThumb(sc.card)!" :alt="sc.card.title" />
          <span v-else class="chip-thumb-empty" />
        </div>
        <span class="chip-name">{{ sc.card.title }}</span>
        <span class="chip-type">{{ sc.card.type }}</span>
        <button
          v-if="idx > 0"
          class="chip-move"
          title="上移"
          @click="moveCard(sc.cardId, -1)"
        >↑</button>
        <button
          v-if="idx < selectedCards.length - 1"
          class="chip-move"
          title="下移"
          @click="moveCard(sc.cardId, 1)"
        >↓</button>
        <button class="chip-remove" title="移除" @click="removeCard(sc.cardId)">×</button>
      </div>
    </div>

    <!-- Search / Add -->
    <div class="picker-input-wrap">
      <input
        v-model="searchQuery"
        type="text"
        class="picker-input"
        placeholder="搜索并添加卡片…"
        @focus="onPickerFocus"
        @blur="onPickerBlur"
      />
      <div v-if="showPicker" class="picker-dropdown">
        <div v-if="loadingCards" class="picker-hint">加载中…</div>
        <div v-else-if="filteredCards.length === 0" class="picker-hint">
          {{ searchQuery ? '无匹配卡片' : '没有可添加的卡片' }}
        </div>
        <div
          v-for="card in filteredCards.slice(0, 20)"
          :key="card.id"
          class="picker-item"
          @mousedown.prevent="addCard(card)"
        >
          <div class="picker-item-thumb">
            <img v-if="cardThumb(card)" :src="cardThumb(card)!" :alt="card.title" />
            <span v-else class="picker-item-thumb-empty" />
          </div>
          <div class="picker-item-info">
            <span class="picker-item-name">{{ card.title }}</span>
            <span class="picker-item-type">{{ card.type }}</span>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
.card-picker {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* ── Selected chips ── */

.selected-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.selected-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 8px;
  background: #efe9de;
  border: 1px solid #e6dfd8;
  border-radius: 8px;
  font-size: 13px;
  color: #3d3d3a;
}

.chip-thumb {
  width: 24px;
  height: 24px;
  border-radius: 4px;
  overflow: hidden;
  flex-shrink: 0;
  background: #e8e0d2;
}

.chip-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.chip-thumb-empty {
  display: block;
  width: 100%;
  height: 100%;
  background: linear-gradient(135deg, #e8e0d2, #ddd6c8);
}

.chip-name {
  max-width: 120px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 500;
}

.chip-type {
  font-size: 11px;
  color: #8b7e6a;
  background: #e8e0d2;
  padding: 1px 5px;
  border-radius: 3px;
}

.chip-move {
  width: 20px;
  height: 20px;
  border: none;
  background: none;
  color: #8b7e6a;
  font-size: 11px;
  cursor: pointer;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}

.chip-move:hover {
  background: #ddd6c8;
  color: #3d3d3a;
}

.chip-remove {
  width: 20px;
  height: 20px;
  border: none;
  background: none;
  color: #8b7e6a;
  font-size: 14px;
  cursor: pointer;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}

.chip-remove:hover {
  background: #fce4e4;
  color: #c64545;
}

/* ── Picker input ── */

.picker-input-wrap {
  position: relative;
}

.picker-input {
  width: 100%;
  padding: 8px 14px;
  border: 1px solid #e6dfd8;
  border-radius: 8px;
  font-size: 13px;
  color: #3d3d3a;
  background: #faf9f5;
  outline: none;
  box-sizing: border-box;
  transition: border-color 0.2s;
}

.picker-input:focus {
  border-color: #cc785c;
}

.picker-input::placeholder {
  color: #b8b2a6;
}

.picker-dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  margin-top: 4px;
  background: #fff;
  border: 1px solid #e6dfd8;
  border-radius: 8px;
  max-height: 260px;
  overflow-y: auto;
  z-index: 10;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
}

.picker-hint {
  padding: 14px;
  font-size: 13px;
  color: #b8b2a6;
  text-align: center;
}

.picker-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 14px;
  cursor: pointer;
  transition: background 0.1s;
}

.picker-item:hover {
  background: #f5f0e8;
}

.picker-item-thumb {
  width: 32px;
  height: 32px;
  border-radius: 4px;
  overflow: hidden;
  flex-shrink: 0;
  background: #e8e0d2;
}

.picker-item-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.picker-item-thumb-empty {
  display: block;
  width: 100%;
  height: 100%;
  background: linear-gradient(135deg, #e8e0d2, #ddd6c8);
}

.picker-item-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.picker-item-name {
  font-size: 13px;
  font-weight: 500;
  color: #3d3d3a;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.picker-item-type {
  font-size: 11px;
  color: #8b7e6a;
}
</style>
