<script setup>
import { ref, nextTick, onMounted, watch, computed } from 'vue'
import { useTranslation } from 'i18next-vue'
import { useRouter } from 'vue-router'
import { useSessions } from '../composables/useSessions.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 { sessions, loading, fetchAll, search } = useSessions()
const { exportAllSessions } = 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: 'session-new' })
}

useKeyboardShortcut('n', goToNew)

const sessionCount = computed(() => sessions.value.length)
const { focusedIndex: focusedSessionIndex } = useListNavigation(sessionCount, (index) => {
  goToDetail(sessions.value[index].id)
})

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

function goToExecute(id, event) {
  event.stopPropagation()
  router.push({ name: 'session-execute', 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 exportAllSessions(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="session-search-toggle"
      :title="$t('sessions.searchPlaceholder')"
      :aria-label="$t('sessions.searchPlaceholder')"
      @click="toggleSearch"
    >
      <i class="bi bi-search"></i>
    </button>
    <button
      data-testid="session-export-btn"
      :title="$t('export.sessions')"
      :aria-label="$t('export.sessions')"
      @click="onExport"
    >
      <i class="bi bi-download"></i>
    </button>
    <button
      data-testid="session-import-btn"
      :title="$t('import.exercises')"
      :aria-label="$t('import.exercises')"
      @click="onImport(false)"
    >
      <i class="bi bi-upload"></i>
    </button>
    <button
      data-testid="session-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="session-new-btn"
      :title="$t('sessions.new') + ' ' + $t('shortcuts.new')"
      :aria-label="$t('sessions.new')"
      @click="goToNew"
    >
      <i class="bi bi-plus-lg"></i>
    </button>
  </Teleport>

  <div class="session-list-view">
    <!-- Search bar -->
    <div v-if="searching" class="search-bar" data-testid="session-search-bar">
      <input
        ref="searchInput"
        v-model="searchQuery"
        type="text"
        :placeholder="$t('sessions.searchPlaceholder')"
        data-testid="session-search-input"
        @blur="onSearchBlur"
      />
      <button
        v-if="searchQuery"
        type="button"
        class="search-clear-btn"
        data-testid="session-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="sessions.length === 0 && !searchQuery.trim()"
      class="text-muted"
      data-testid="session-empty"
    >
      {{ $t('sessions.empty') }}
    </p>

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

    <!-- Session cards -->
    <div
      v-for="(session, index) in sessions"
      :key="session.id"
      class="card session-card"
      :class="{ 'card-focused': focusedSessionIndex === index }"
      :data-testid="'session-card-' + session.id"
      :data-list-index="index"
      tabindex="0"
      @click="goToDetail(session.id)"
    >
      <div class="session-card-header">
        <h3 data-testid="session-card-title">{{ session.title }}</h3>
        <span
          v-if="session.items && session.items.length"
          class="badge badge-info"
          data-testid="session-card-item-count"
        >
          {{ session.items.length }} {{ $t('sessions.items') }}
        </span>
        <button
          class="card-play-btn"
          :data-testid="'session-card-play-' + session.id"
          :title="$t('execution.start')"
          :aria-label="$t('execution.start')"
          @click="goToExecute(session.id, $event)"
        >
          <i class="bi bi-play-fill"></i>
        </button>
      </div>
    </div>
  </div>

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

<style scoped>
.session-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;
}

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

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

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

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

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

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

.card-play-btn {
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: none;
  background: var(--btn-primary-bg);
  color: var(--btn-primary-color);
  cursor: pointer;
  flex-shrink: 0;
  font-size: 14px;
  transition: opacity 0.15s;
}

.card-play-btn:hover {
  opacity: 0.8;
}

.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-info {
  background-color: var(--front-color2);
}
</style>
