<script setup>
import { ref, nextTick, onMounted, watch, computed } from 'vue'
import { useTranslation } from 'i18next-vue'
import { useRouter } from 'vue-router'
import { useCombos } from '../composables/useCombos.js'
import { useJsonExport } from '../composables/useJsonExport.js'
import { useJsonImport } from '../composables/useJsonImport.js'
import { useSettings } from '../composables/useSettings.js'
import { useKeyboardShortcut } from '../composables/useKeyboardShortcut.js'
import { useListNavigation } from '../composables/useListNavigation.js'
import ImportDialog from '../components/ImportDialog.vue'

const { t } = useTranslation()
const router = useRouter()
const { combos, loading, fetchAll, search } = useCombos()
const { exportAllCombos } = useJsonExport()
const { loadFile } = useJsonImport()
const { settings, fetchAll: fetchSettings } = useSettings()
const localUuid = ref('')

// Import dialog state
const showImportDialog = ref(false)
const importEnvelope = ref(null)
const importAsMine = ref(false)

const searchQuery = ref('')
const searching = ref(false)
const searchInput = ref(null)

onMounted(async () => {
  fetchAll()
  await fetchSettings()
  localUuid.value = settings.value.user_uuid || ''
})

let searchTimeout = null
watch(searchQuery, (query) => {
  clearTimeout(searchTimeout)
  const trimmed = query.trim()
  if (!trimmed) {
    fetchAll()
    return
  }
  searchTimeout = setTimeout(() => {
    search(trimmed)
  }, 250)
})

function goToNew() {
  router.push({ name: 'combo-new' })
}

useKeyboardShortcut('n', goToNew)

const comboCount = computed(() => combos.value.length)
const { focusedIndex: focusedComboIndex } = useListNavigation(comboCount, (index) => {
  goToDetail(combos.value[index].id)
})

function goToDetail(id) {
  router.push({ name: 'combo-detail', params: { id } })
}

function toggleSearch() {
  searching.value = !searching.value
  if (searching.value) {
    nextTick(() => {
      searchInput.value?.focus()
    })
  } else {
    searchQuery.value = ''
    fetchAll()
  }
}

function onSearchBlur() {
  if (!searchQuery.value.trim()) {
    searching.value = false
  }
}

function clearSearch() {
  searchQuery.value = ''
  searchInput.value?.focus()
}

async function onExport() {
  await exportAllCombos(searchQuery.value.trim())
}

async function onImport(asMine = false) {
  const result = await loadFile()
  if (result.cancelled) return
  if (result.error) {
    window.alert(t(result.error))
    return
  }
  importEnvelope.value = result.envelope
  importAsMine.value = asMine
  showImportDialog.value = true
}

function onImportDone() {
  showImportDialog.value = false
  importEnvelope.value = null
  importAsMine.value = false
  fetchAll()
}

function onImportClose() {
  showImportDialog.value = false
  importEnvelope.value = null
  importAsMine.value = false
}
</script>

<template>
  <Teleport to="#actionbar-actions" defer>
    <button
      data-testid="combo-search-toggle"
      :title="$t('combos.searchPlaceholder')"
      :aria-label="$t('combos.searchPlaceholder')"
      @click="toggleSearch"
    >
      <i class="bi bi-search"></i>
    </button>
    <button
      data-testid="combo-export-btn"
      :title="$t('export.combos')"
      :aria-label="$t('export.combos')"
      @click="onExport"
    >
      <i class="bi bi-download"></i>
    </button>
    <button
      data-testid="combo-import-btn"
      :title="$t('import.exercises')"
      :aria-label="$t('import.exercises')"
      @click="onImport(false)"
    >
      <i class="bi bi-upload"></i>
    </button>
    <button
      data-testid="combo-import-as-mine-btn"
      :title="$t('import.importAsMine')"
      :aria-label="$t('import.importAsMine')"
      @click="onImport(true)"
    >
      <i class="bi bi-person-check"></i>
    </button>
    <button
      data-testid="combo-new-btn"
      :title="$t('combos.new') + ' ' + $t('shortcuts.new')"
      :aria-label="$t('combos.new')"
      @click="goToNew"
    >
      <i class="bi bi-plus-lg"></i>
    </button>
  </Teleport>

  <div class="combo-list-view">
    <!-- Search bar -->
    <div v-if="searching" class="search-bar" data-testid="combo-search-bar">
      <input
        ref="searchInput"
        v-model="searchQuery"
        type="text"
        :placeholder="$t('combos.searchPlaceholder')"
        data-testid="combo-search-input"
        @blur="onSearchBlur"
      />
      <button
        v-if="searchQuery"
        type="button"
        class="search-clear-btn"
        data-testid="combo-search-clear"
        :title="$t('common.clearSearch')"
        :aria-label="$t('common.clearSearch')"
        @mousedown.prevent="clearSearch"
      >
        <i class="bi bi-x-lg"></i>
      </button>
    </div>

    <!-- Loading state -->
    <p v-if="loading" class="text-muted">{{ $t('app.loading') }}</p>

    <!-- Empty state -->
    <p
      v-else-if="combos.length === 0 && !searchQuery.trim()"
      class="text-muted"
      data-testid="combo-empty"
    >
      {{ $t('combos.empty') }}
    </p>

    <!-- No search results -->
    <p
      v-else-if="combos.length === 0 && searchQuery.trim()"
      class="text-muted"
      data-testid="combo-no-results"
    >
      {{ $t('combos.noResults') }}
    </p>

    <!-- Combo cards -->
    <div
      v-for="(combo, index) in combos"
      :key="combo.id"
      class="card combo-card"
      :class="{ 'card-focused': focusedComboIndex === index }"
      :data-testid="'combo-card-' + combo.id"
      :data-list-index="index"
      tabindex="0"
      @click="goToDetail(combo.id)"
    >
      <div class="combo-card-header">
        <h3 data-testid="combo-card-title">{{ combo.title }}</h3>
        <div class="combo-card-badges">
          <span class="badge badge-type" data-testid="combo-card-type">
            {{ $t(`combos.types.${combo.type.toLowerCase()}`) }}
          </span>
          <span
            v-if="combo.exercises && combo.exercises.length"
            class="badge badge-info"
            data-testid="combo-card-exercise-count"
          >
            {{ combo.exercises.length }} {{ $t('combos.exercises') }}
          </span>
        </div>
      </div>
    </div>
  </div>

  <ImportDialog
    v-if="showImportDialog && importEnvelope"
    :envelope="importEnvelope"
    :local-uuid="localUuid"
    :as-mine="importAsMine"
    @done="onImportDone"
    @close="onImportClose"
  />
</template>

<style scoped>
.combo-list-view {
  max-width: 800px;
}

.search-bar {
  position: relative;
  margin-bottom: 16px;
}

.search-bar input {
  padding-right: 36px;
}

.search-clear-btn {
  position: absolute;
  top: 50%;
  right: 8px;
  transform: translateY(-50%);
  background: none;
  border: none;
  padding: 4px;
  line-height: 1;
  color: var(--front-color2);
  cursor: pointer;
}

.combo-card {
  cursor: pointer;
  transition: border-color 0.15s;
}

.combo-card:hover {
  border-color: var(--btn-primary-bg);
}

.combo-card:focus-visible {
  border-color: var(--btn-primary-bg);
  box-shadow: 0 0 0 2px var(--btn-primary-bg);
  outline: none;
}

.combo-card.card-focused {
  border-color: var(--btn-primary-bg);
  box-shadow: 0 0 0 2px var(--btn-primary-bg);
}

.combo-card-header {
  display: flex;
  align-items: center;
  gap: 8px;
}

.combo-card-header h3 {
  flex: 1;
  font-size: 16px;
  font-weight: 600;
}

.combo-card-badges {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
}

.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: 12px;
  font-size: 12px;
  background-color: var(--btn-primary-bg);
  color: var(--btn-primary-color);
  white-space: nowrap;
}

.badge-type {
  background-color: var(--front-color2);
}

.badge-info {
  background-color: var(--front-color2);
}
</style>
