<script setup>
import { ref, computed, onMounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useCollections } from '../composables/useCollections.js'
import { useSessions } from '../composables/useSessions.js'
import { useSettings } from '../composables/useSettings.js'
import { validateRequired } from '../utils/validation.js'
import { collectionRepository } from '../db/repositories/collectionRepository.js'
import { useKeyboardShortcut } from '../composables/useKeyboardShortcut.js'

const router = useRouter()
const route = useRoute()
const { create, update, getById } = useCollections()
const { sessions: allSessions, fetchAll: fetchSessions } = useSessions()
const { get: getSetting } = useSettings()

const isEdit = computed(() => route.name === 'collection-edit')
const collectionId = computed(() => route.params.id)

const label = ref('')
const selectedSessions = ref([])

const errors = ref({})
const saving = ref(false)

const newSessionId = ref('')

onMounted(async () => {
  await fetchSessions()

  if (isEdit.value && collectionId.value) {
    const collection = await getById(collectionId.value)
    if (!collection) {
      router.replace({ name: 'collections' })
      return
    }
    label.value = collection.label
    selectedSessions.value = (collection.sessions || []).map((s) => s.session_id)
  }
})

function validate() {
  const e = {}
  const labelErr = validateRequired(label.value)
  if (labelErr) e.label = labelErr
  errors.value = e
  return Object.keys(e).length === 0
}

function addSession() {
  if (!newSessionId.value) return
  if (selectedSessions.value.includes(newSessionId.value)) return
  selectedSessions.value.push(newSessionId.value)
  newSessionId.value = ''
}

function removeSession(index) {
  selectedSessions.value.splice(index, 1)
}

function moveSessionUp(index) {
  if (index === 0) return
  const arr = selectedSessions.value
  ;[arr[index - 1], arr[index]] = [arr[index], arr[index - 1]]
}

function moveSessionDown(index) {
  if (index === selectedSessions.value.length - 1) return
  const arr = selectedSessions.value
  ;[arr[index], arr[index + 1]] = [arr[index + 1], arr[index]]
}

function getSessionTitle(sessionId) {
  const session = allSessions.value.find((s) => s.id === sessionId)
  return session ? session.title : sessionId
}

async function onSave() {
  if (!validate()) return

  saving.value = true
  try {
    const userUuid = await getSetting('user_uuid')
    const data = {
      label: label.value.trim(),
      created_by: userUuid,
    }

    let id
    if (isEdit.value) {
      await update(collectionId.value, data)
      id = collectionId.value
    } else {
      id = await create(data)
    }

    await collectionRepository.setSessions(id, selectedSessions.value)

    router.push({ name: 'collection-detail', params: { id } })
  } catch (e) {
    if (e.message && e.message.includes('UNIQUE')) {
      errors.value = { ...errors.value, label: 'validation.collectionLabelTaken' }
    } else {
      errors.value = { ...errors.value, save: e.message }
    }
  } finally {
    saving.value = false
  }
}

useKeyboardShortcut('enter', onSave, { ctrl: true, ignoreInputs: false })
useKeyboardShortcut('escape', onCancel, { ignoreInputs: false })

function onCancel() {
  if (isEdit.value) {
    router.push({ name: 'collection-detail', params: { id: collectionId.value } })
  } else {
    router.push({ name: 'collections' })
  }
}
</script>

<template>
  <Teleport to="#actionbar-actions" defer>
    <button
      data-testid="collection-form-cancel"
      :title="$t('collections.form.cancel')"
      :aria-label="$t('collections.form.cancel')"
      @click="onCancel"
    >
      <i class="bi bi-x-lg"></i>
    </button>
  </Teleport>

  <div class="collection-form-view">
    <h2 data-testid="collection-form-heading">
      {{ isEdit ? $t('collections.edit') : $t('collections.new') }}
    </h2>

    <form novalidate @submit.prevent="onSave">
      <div class="form-group">
        <label for="collection-label">{{ $t('collections.form.label') }} *</label>
        <input
          id="collection-label"
          v-model="label"
          data-testid="collection-label"
          type="text"
          :placeholder="$t('collections.form.labelPlaceholder')"
          :class="{ 'input-error': errors.label }"
          required
          aria-required="true"
          :aria-describedby="errors.label ? 'collection-label-error' : undefined"
        />
        <p
          v-if="errors.label"
          id="collection-label-error"
          role="alert"
          class="field-error"
          data-testid="collection-label-error"
        >
          {{ $t(errors.label) }}
        </p>
      </div>

      <div class="form-group">
        <label>{{ $t('collections.form.sessions') }}</label>

        <ol v-if="selectedSessions.length" class="session-order-list">
          <li
            v-for="(sessionId, index) in selectedSessions"
            :key="'session-' + index"
            class="session-order-item"
            :data-testid="'collection-session-' + index"
          >
            <span class="session-order-number">{{ index + 1 }}</span>
            <span class="session-order-title">{{ getSessionTitle(sessionId) }}</span>
            <div class="session-order-actions">
              <button
                type="button"
                class="btn-move"
                :data-testid="'collection-session-move-up-' + index"
                :disabled="index === 0"
                @click="moveSessionUp(index)"
              >
                <i class="bi bi-chevron-up"></i>
              </button>
              <button
                type="button"
                class="btn-move"
                :data-testid="'collection-session-move-down-' + index"
                :disabled="index === selectedSessions.length - 1"
                @click="moveSessionDown(index)"
              >
                <i class="bi bi-chevron-down"></i>
              </button>
              <button
                type="button"
                class="btn-remove"
                :data-testid="'collection-session-remove-' + index"
                @click="removeSession(index)"
              >
                <i class="bi bi-trash"></i>
              </button>
            </div>
          </li>
        </ol>

        <div class="session-add">
          <select
            v-model="newSessionId"
            data-testid="collection-session-select"
            :disabled="allSessions.length === 0"
          >
            <option value="" disabled>
              {{
                allSessions.length === 0
                  ? $t('collections.form.noSessions')
                  : $t('collections.form.selectSession')
              }}
            </option>
            <option v-for="session in allSessions" :key="session.id" :value="session.id">
              {{ session.title }}
            </option>
          </select>
          <button
            type="button"
            class="btn btn-primary btn-sm"
            data-testid="collection-session-add"
            :disabled="!newSessionId"
            @click="addSession"
          >
            <i class="bi bi-plus"></i> {{ $t('collections.form.addSession') }}
          </button>
        </div>
      </div>

      <p v-if="errors.save" class="field-error" data-testid="collection-save-error">
        {{ errors.save }}
      </p>

      <div class="form-actions">
        <button
          type="submit"
          class="btn btn-primary"
          data-testid="collection-save"
          :disabled="saving"
          :title="$t('collections.form.save') + ' ' + $t('shortcuts.save')"
        >
          <i class="bi bi-check-lg"></i>
          {{ $t('collections.form.save') }}
        </button>
        <button
          type="button"
          class="btn"
          data-testid="collection-form-cancel-btn"
          @click="onCancel"
        >
          {{ $t('collections.form.cancel') }}
        </button>
      </div>
    </form>
  </div>
</template>

<style scoped>
.collection-form-view {
  max-width: 600px;
}

.collection-form-view h2 {
  margin-bottom: 16px;
  font-size: 20px;
}

.form-group {
  margin-bottom: 16px;
}

.form-group label {
  display: block;
  font-weight: 600;
  font-size: 14px;
  margin-bottom: 4px;
}

.input-error {
  border-color: var(--btn-danger-bg) !important;
}

.field-error {
  color: var(--btn-danger-bg);
  font-size: 13px;
  margin: 4px 0 0;
}

select {
  width: 100%;
  padding: 8px 12px;
  border: 1px solid var(--border-color);
  border-radius: 4px;
  background-color: var(--color-background);
  color: var(--color-text);
  font-size: 14px;
}

.session-order-list {
  list-style: none;
  padding: 0;
  margin: 0 0 8px;
}

.session-order-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 4px;
  border-bottom: 1px solid var(--border-color);
}

.session-order-number {
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background-color: var(--btn-primary-bg);
  color: var(--btn-primary-color);
  font-size: 12px;
  font-weight: 600;
  flex-shrink: 0;
}

.session-order-title {
  flex: 1;
  font-size: 14px;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.session-order-actions {
  display: flex;
  gap: 4px;
  flex-shrink: 0;
}

.btn-move {
  background: none;
  border: none;
  color: var(--color-text);
  cursor: pointer;
  padding: 4px;
  font-size: 14px;
  display: flex;
  align-items: center;
}

.btn-move:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}

.btn-move:hover:not(:disabled) {
  color: var(--btn-primary-bg);
}

.btn-remove {
  background: none;
  border: none;
  color: var(--btn-danger-bg);
  cursor: pointer;
  padding: 4px;
  font-size: 14px;
  display: flex;
  align-items: center;
}

.btn-remove:hover {
  opacity: 0.7;
}

.session-add {
  display: flex;
  gap: 8px;
  align-items: flex-start;
}

.session-add select {
  flex: 1;
}

.btn-sm {
  padding: 6px 12px;
  font-size: 13px;
  white-space: nowrap;
}

.form-actions {
  display: flex;
  gap: 8px;
  margin-top: 24px;
}

@media screen and (max-width: 400px) {
  .session-order-item {
    flex-wrap: wrap;
  }

  .session-order-number {
    display: none;
  }

  .session-order-actions {
    order: 2;
  }

  .form-actions {
    flex-wrap: wrap;
  }

  .form-actions .btn {
    flex: 1 1 auto;
    justify-content: center;
  }
}
</style>
