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

const { t } = useTranslation()
const router = useRouter()
const route = useRoute()
const { create, update, getById } = useSessions()
const { exercises: allExercises, fetchAll: fetchExercises } = useExercises()
const { combos: allCombos, fetchAll: fetchCombos } = useCombos()
const { get: getSetting } = useSettings()

const isEdit = computed(() => route.name === 'session-edit')
const sessionId = computed(() => route.params.id)

// Form fields
const title = ref('')
const description = ref('')
const selectedItems = ref([])

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

// Item selector
const newItemType = ref('exercise')
const newItemId = ref('')

onMounted(async () => {
  await fetchExercises()
  await fetchCombos()

  if (isEdit.value && sessionId.value) {
    const session = await getById(sessionId.value)
    if (!session) {
      router.replace({ name: 'sessions' })
      return
    }
    title.value = session.title
    description.value = session.description || ''
    selectedItems.value = (session.items || []).map((item) => {
      let asymmetric = false
      if (item.item_type === 'exercise') {
        const ex = allExercises.value.find((e) => e.id === item.item_id)
        asymmetric = ex?.asymmetric || false
      }
      return {
        item_id: item.item_id,
        item_type: item.item_type,
        repetitions: item.repetitions || 1,
        weight: item.weight || 0.0,
        asymmetric,
      }
    })
  }
})

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

function addItem() {
  if (!newItemId.value) return
  let repetitions = 1
  let asymmetric = false
  if (newItemType.value === 'exercise') {
    const ex = allExercises.value.find((e) => e.id === newItemId.value)
    repetitions = ex?.default_reps || 1
    asymmetric = ex?.asymmetric || false
    if (asymmetric && repetitions % 2 !== 0) repetitions++
  } else if (newItemType.value === 'combo') {
    const combo = allCombos.value.find((c) => c.id === newItemId.value)
    if (combo?.type === 'EMOM') {
      repetitions = combo.timer_config?.duration || 1
    }
  }
  selectedItems.value.push({
    item_id: newItemId.value,
    item_type: newItemType.value,
    repetitions,
    weight: 0.0,
    asymmetric,
  })
  newItemId.value = ''
}

function enforceEvenReps(item) {
  if (item.asymmetric && item.repetitions > 0 && item.repetitions % 2 !== 0) {
    item.repetitions++
  }
}

function removeItem(index) {
  selectedItems.value.splice(index, 1)
}

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

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

function getItemTitle(item) {
  if (item.item_type === 'exercise') {
    const ex = allExercises.value.find((e) => e.id === item.item_id)
    return ex ? ex.title : item.item_id
  }
  const combo = allCombos.value.find((c) => c.id === item.item_id)
  return combo ? combo.title : item.item_id
}

function getItemTypeLabel(itemType) {
  return itemType === 'exercise' ? t('sessions.itemType.exercise') : t('sessions.itemType.combo')
}

function getItemComboType(item) {
  if (item.item_type !== 'combo') return null
  const combo = allCombos.value.find((c) => c.id === item.item_id)
  return combo?.type || null
}

function repsLabel(item) {
  const comboType = getItemComboType(item)
  return comboType === 'AMRAP' || comboType === 'EMOM'
    ? t('sessions.form.durationMin')
    : t('sessions.form.reps')
}

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

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

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

    // Save items
    await sessionRepository.setItems(id, selectedItems.value)

    router.push({ name: 'session-detail', params: { id } })
  } catch (e) {
    if (e.message && e.message.includes('UNIQUE')) {
      errors.value = { ...errors.value, title: 'validation.titleTaken' }
    } 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: 'session-detail', params: { id: sessionId.value } })
  } else {
    router.push({ name: 'sessions' })
  }
}
</script>

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

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

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

      <!-- Description -->
      <div class="form-group">
        <label for="session-description">
          {{ $t('sessions.form.description') }}
          <span class="field-hint">{{ $t('common.markdownHint') }}</span>
        </label>
        <textarea
          id="session-description"
          v-model="description"
          data-testid="session-description"
          :placeholder="$t('sessions.form.descriptionPlaceholder')"
          rows="3"
        ></textarea>
      </div>

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

        <!-- Selected items list -->
        <ol v-if="selectedItems.length" class="item-order-list">
          <li
            v-for="(item, index) in selectedItems"
            :key="'item-' + index"
            class="item-order-item"
            :data-testid="'session-item-' + index"
          >
            <span class="item-order-number">{{ index + 1 }}</span>
            <span class="item-order-type">{{ getItemTypeLabel(item.item_type) }}</span>
            <span class="item-order-title">{{ getItemTitle(item) }}</span>
            <div class="item-order-fields">
              <div class="item-field">
                <label :for="'session-item-reps-' + index">{{ repsLabel(item) }}</label>
                <div class="stepper">
                  <button
                    type="button"
                    class="stepper-btn btn-primary"
                    @click="
                      item.repetitions = Math.max(
                        item.asymmetric ? 2 : 1,
                        item.repetitions - (item.asymmetric ? 2 : 1),
                      )
                    "
                  >
                    <i class="bi bi-dash-circle-fill"></i>
                  </button>
                  <input
                    :id="'session-item-reps-' + index"
                    v-model.number="item.repetitions"
                    :data-testid="'session-item-reps-' + index"
                    type="number"
                    :min="item.asymmetric ? 2 : 1"
                    :step="item.asymmetric ? 2 : 1"
                    class="step-input"
                    @change="enforceEvenReps(item)"
                  />
                  <button
                    type="button"
                    class="stepper-btn btn-primary"
                    @click="item.repetitions += item.asymmetric ? 2 : 1"
                  >
                    <i class="bi bi-plus-circle-fill"></i>
                  </button>
                  <button
                    type="button"
                    class="stepper-btn stepper-btn-fast"
                    @click="item.repetitions += item.asymmetric ? 10 : 5"
                  >
                    <i class="bi bi-forward-fill"></i>
                  </button>
                </div>
              </div>
              <div v-if="item.item_type === 'exercise'" class="item-field">
                <label :for="'session-item-weight-' + index">{{
                  $t('sessions.form.weight')
                }}</label>
                <div class="stepper">
                  <button
                    type="button"
                    class="stepper-btn btn-primary"
                    @click="item.weight = Math.max(0, +(item.weight - 0.5).toFixed(1))"
                  >
                    <i class="bi bi-dash-circle-fill"></i>
                  </button>
                  <input
                    :id="'session-item-weight-' + index"
                    v-model.number="item.weight"
                    :data-testid="'session-item-weight-' + index"
                    type="number"
                    min="0"
                    step="0.5"
                    class="step-input"
                  />
                  <button
                    type="button"
                    class="stepper-btn btn-primary"
                    @click="item.weight = +(item.weight + 0.5).toFixed(1)"
                  >
                    <i class="bi bi-plus-circle-fill"></i>
                  </button>
                  <button
                    type="button"
                    class="stepper-btn stepper-btn-fast"
                    @click="item.weight = +(item.weight + 1).toFixed(1)"
                  >
                    <i class="bi bi-forward-fill"></i>
                  </button>
                </div>
              </div>
            </div>
            <div class="item-order-actions">
              <button
                type="button"
                class="btn-move"
                :data-testid="'session-item-move-up-' + index"
                :disabled="index === 0"
                @click="moveItemUp(index)"
              >
                <i class="bi bi-chevron-up"></i>
              </button>
              <button
                type="button"
                class="btn-move"
                :data-testid="'session-item-move-down-' + index"
                :disabled="index === selectedItems.length - 1"
                @click="moveItemDown(index)"
              >
                <i class="bi bi-chevron-down"></i>
              </button>
              <button
                type="button"
                class="btn-remove"
                :data-testid="'session-item-remove-' + index"
                @click="removeItem(index)"
              >
                <i class="bi bi-trash"></i>
              </button>
            </div>
          </li>
        </ol>
        <p v-if="selectedItems.some((i) => i.asymmetric)" class="field-hint">
          {{ $t('exercises.evenRepsHint') }}
        </p>

        <!-- Add item -->
        <div class="item-add">
          <select v-model="newItemType" data-testid="session-item-type-select">
            <option value="exercise">{{ $t('sessions.itemType.exercise') }}</option>
            <option value="combo">{{ $t('sessions.itemType.combo') }}</option>
          </select>
          <select
            v-model="newItemId"
            data-testid="session-item-select"
            :disabled="
              (newItemType === 'exercise' && allExercises.length === 0) ||
              (newItemType === 'combo' && allCombos.length === 0)
            "
          >
            <option value="" disabled>
              {{
                newItemType === 'exercise'
                  ? allExercises.length === 0
                    ? $t('sessions.form.noExercises')
                    : $t('sessions.form.selectExercise')
                  : allCombos.length === 0
                    ? $t('sessions.form.noCombos')
                    : $t('sessions.form.selectCombo')
              }}
            </option>
            <template v-if="newItemType === 'exercise'">
              <option v-for="ex in allExercises" :key="ex.id" :value="ex.id">
                {{ ex.title }}
              </option>
            </template>
            <template v-else>
              <option v-for="combo in allCombos" :key="combo.id" :value="combo.id">
                {{ combo.title }}
              </option>
            </template>
          </select>
          <button
            type="button"
            class="btn btn-primary btn-sm"
            data-testid="session-item-add"
            :disabled="!newItemId"
            @click="addItem"
          >
            <i class="bi bi-plus"></i> {{ $t('sessions.form.addItem') }}
          </button>
        </div>
      </div>

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

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

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

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

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

.form-group label {
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-weight: 600;
  font-size: 14px;
  margin-bottom: 4px;
}

.field-hint {
  font-weight: 400;
  font-size: 11px;
  opacity: 0.55;
}

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

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

.field-hint {
  color: var(--color-text-muted);
  font-size: 12px;
  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;
}

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

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

.item-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;
}

.item-order-type {
  font-size: 11px;
  padding: 2px 6px;
  border-radius: 4px;
  background-color: var(--front-color2);
  color: var(--btn-primary-color);
  flex-shrink: 0;
}

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

.item-order-fields {
  order: 3;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.item-field {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 8px;
}

.item-field label {
  font-size: 12px;
  font-weight: 600;
  color: var(--color-text-muted);
  width: 90px;
  flex-shrink: 0;
  white-space: nowrap;
}

.stepper {
  display: flex;
  align-items: center;
  gap: 4px;
}

.stepper-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-size: 18px;
  flex-shrink: 0;
  transition: opacity 0.15s;
}

.stepper-btn:hover {
  opacity: 0.8;
}

.stepper-btn:active {
  opacity: 0.6;
}

.stepper-btn-fast {
  background: var(--btn-primary-bg);
  color: var(--btn-primary-color);
}

.step-input {
  width: 56px;
  padding: 4px 2px;
  border: 1px solid var(--border-color);
  border-radius: 6px;
  background: var(--color-background);
  color: var(--color-text);
  font-size: 15px;
  font-weight: 600;
  text-align: center;
}

.item-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;
}

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

.item-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) {
  .item-order-number {
    display: none;
  }

  .item-order-title {
    flex: 1 1 auto;
  }

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

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

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