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

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

const isEdit = computed(() => route.name === 'combo-edit')
const comboId = computed(() => route.params.id)

// Form fields
const title = ref('')
const description = ref('')
const type = ref('NONE')
const selectedExercises = ref([])
const timerConfig = ref({})

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

const newExerciseId = ref('')

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

  if (isEdit.value && comboId.value) {
    const combo = await getById(comboId.value)
    if (!combo) {
      router.replace({ name: 'combos' })
      return
    }
    title.value = combo.title
    description.value = combo.description || ''
    type.value = combo.type
    selectedExercises.value = (combo.exercises || []).map((e) => {
      const ex = allExercises.value.find((a) => a.id === e.exercise_id)
      return {
        exerciseId: e.exercise_id,
        defaultReps: e.default_reps || 1,
        defaultWeight: e.default_weight || 0.0,
        asymmetric: ex?.asymmetric || false,
      }
    })
    timerConfig.value = { ...combo.timer_config }
  }
})

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

function addExercise() {
  if (!newExerciseId.value) return
  const ex = allExercises.value.find((e) => e.id === newExerciseId.value)
  const asymmetric = ex?.asymmetric || false
  let defaultReps = ex?.default_reps || 1
  if (asymmetric && defaultReps % 2 !== 0) defaultReps++
  selectedExercises.value.push({
    exerciseId: newExerciseId.value,
    defaultReps,
    defaultWeight: 0.0,
    asymmetric,
  })
  newExerciseId.value = ''
}

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

function removeExercise(index) {
  selectedExercises.value.splice(index, 1)
}

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

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

function getExerciseTitle(exerciseId) {
  const ex = allExercises.value.find((e) => e.id === exerciseId)
  return ex ? ex.title : exerciseId
}

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(),
      type: type.value,
      timer_config: timerConfig.value,
      created_by: userUuid,
    }

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

    // Save exercises
    await comboRepository.setExercises(id, selectedExercises.value)

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

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

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

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

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

      <!-- Type -->
      <div class="form-group">
        <label for="combo-type">{{ $t('combos.form.type') }}</label>
        <select id="combo-type" v-model="type" data-testid="combo-type">
          <option value="NONE">{{ $t('combos.types.none') }}</option>
          <option value="EMOM">{{ $t('combos.types.emom') }}</option>
          <option value="AMRAP">{{ $t('combos.types.amrap') }}</option>
          <option value="TABATA">{{ $t('combos.types.tabata') }}</option>
        </select>
      </div>

      <!-- Timer config for EMOM -->
      <div v-if="type === 'EMOM'" class="form-group form-sub-group">
        <label for="combo-emom-duration">{{ $t('combos.timer.emomDuration') }}</label>
        <input
          id="combo-emom-duration"
          v-model.number="timerConfig.duration"
          data-testid="combo-emom-duration"
          type="number"
          min="1"
          :placeholder="$t('combos.timer.minutes')"
        />
      </div>

      <!-- Timer config for AMRAP -->
      <div v-if="type === 'AMRAP'" class="form-group form-sub-group">
        <label for="combo-amrap-duration">{{ $t('combos.timer.amrapDuration') }}</label>
        <input
          id="combo-amrap-duration"
          v-model.number="timerConfig.duration"
          data-testid="combo-amrap-duration"
          type="number"
          min="1"
          :placeholder="$t('combos.timer.minutes')"
        />
      </div>

      <!-- Timer config for TABATA -->
      <div v-if="type === 'TABATA'" class="form-group form-sub-group">
        <label for="combo-tabata-work-time">{{ $t('combos.timer.tabataWorkTime') }}</label>
        <input
          id="combo-tabata-work-time"
          v-model.number="timerConfig.workTime"
          data-testid="combo-tabata-work-time"
          type="number"
          min="1"
          :placeholder="$t('combos.timer.tabataSeconds')"
        />
      </div>
      <div v-if="type === 'TABATA'" class="form-group form-sub-group">
        <label for="combo-tabata-rest-time">{{ $t('combos.timer.tabataRestTime') }}</label>
        <input
          id="combo-tabata-rest-time"
          v-model.number="timerConfig.restTime"
          data-testid="combo-tabata-rest-time"
          type="number"
          min="0"
          :placeholder="$t('combos.timer.tabataSeconds')"
        />
      </div>

      <!-- Exercise selector -->
      <div class="form-group">
        <label>{{ $t('combos.form.exercises') }}</label>

        <!-- Selected exercises list -->
        <ol v-if="selectedExercises.length" class="exercise-order-list">
          <li
            v-for="(exercise, index) in selectedExercises"
            :key="'ex-' + index"
            class="exercise-order-item"
            :data-testid="'combo-exercise-item-' + index"
          >
            <span class="exercise-order-number">{{ index + 1 }}</span>
            <span class="exercise-order-title">{{ getExerciseTitle(exercise.exerciseId) }}</span>
            <div class="exercise-order-fields">
              <div class="exercise-field">
                <label :for="'combo-exercise-reps-' + index">{{ $t('combos.form.reps') }}</label>
                <div class="stepper">
                  <button
                    type="button"
                    class="stepper-btn btn-primary"
                    @click="
                      exercise.defaultReps = Math.max(
                        exercise.asymmetric ? 2 : 1,
                        exercise.defaultReps - (exercise.asymmetric ? 2 : 1),
                      )
                    "
                  >
                    <i class="bi bi-dash-circle-fill"></i>
                  </button>
                  <input
                    :id="'combo-exercise-reps-' + index"
                    v-model.number="exercise.defaultReps"
                    :data-testid="'combo-exercise-reps-' + index"
                    type="number"
                    :min="exercise.asymmetric ? 2 : 1"
                    :step="exercise.asymmetric ? 2 : 1"
                    class="step-input"
                    @change="enforceEvenReps(exercise)"
                  />
                  <button
                    type="button"
                    class="stepper-btn btn-primary"
                    @click="exercise.defaultReps += exercise.asymmetric ? 2 : 1"
                  >
                    <i class="bi bi-plus-circle-fill"></i>
                  </button>
                  <button
                    type="button"
                    class="stepper-btn stepper-btn-fast"
                    @click="exercise.defaultReps += exercise.asymmetric ? 10 : 5"
                  >
                    <i class="bi bi-forward-fill"></i>
                  </button>
                </div>
              </div>
              <div class="exercise-field">
                <label :for="'combo-exercise-weight-' + index">{{
                  $t('combos.form.weight')
                }}</label>
                <div class="stepper">
                  <button
                    type="button"
                    class="stepper-btn btn-primary"
                    @click="
                      exercise.defaultWeight = Math.max(
                        0,
                        +(exercise.defaultWeight - 0.5).toFixed(1),
                      )
                    "
                  >
                    <i class="bi bi-dash-circle-fill"></i>
                  </button>
                  <input
                    :id="'combo-exercise-weight-' + index"
                    v-model.number="exercise.defaultWeight"
                    :data-testid="'combo-exercise-weight-' + index"
                    type="number"
                    min="0"
                    step="0.5"
                    class="step-input"
                  />
                  <button
                    type="button"
                    class="stepper-btn btn-primary"
                    @click="exercise.defaultWeight = +(exercise.defaultWeight + 0.5).toFixed(1)"
                  >
                    <i class="bi bi-plus-circle-fill"></i>
                  </button>
                  <button
                    type="button"
                    class="stepper-btn stepper-btn-fast"
                    @click="exercise.defaultWeight = +(exercise.defaultWeight + 1).toFixed(1)"
                  >
                    <i class="bi bi-forward-fill"></i>
                  </button>
                </div>
              </div>
            </div>
            <div class="exercise-order-actions">
              <button
                type="button"
                class="btn-move"
                :data-testid="'combo-exercise-move-up-' + index"
                :disabled="index === 0"
                @click="moveExerciseUp(index)"
              >
                <i class="bi bi-chevron-up"></i>
              </button>
              <button
                type="button"
                class="btn-move"
                :data-testid="'combo-exercise-move-down-' + index"
                :disabled="index === selectedExercises.length - 1"
                @click="moveExerciseDown(index)"
              >
                <i class="bi bi-chevron-down"></i>
              </button>
              <button
                type="button"
                class="btn-remove"
                :data-testid="'combo-exercise-remove-' + index"
                @click="removeExercise(index)"
              >
                <i class="bi bi-trash"></i>
              </button>
            </div>
          </li>
        </ol>
        <p v-if="selectedExercises.some((e) => e.asymmetric)" class="field-hint">
          {{ $t('exercises.evenRepsHint') }}
        </p>

        <!-- Add exercise -->
        <div class="exercise-add">
          <select
            v-model="newExerciseId"
            data-testid="combo-exercise-select"
            :disabled="allExercises.length === 0"
          >
            <option value="" disabled>
              {{
                allExercises.length === 0
                  ? $t('combos.form.noExercises')
                  : $t('combos.form.selectExercise')
              }}
            </option>
            <option v-for="ex in allExercises" :key="ex.id" :value="ex.id">
              {{ ex.title }}
            </option>
          </select>
          <button
            type="button"
            class="btn btn-primary btn-sm"
            data-testid="combo-exercise-add"
            :disabled="!newExerciseId"
            @click="addExercise"
          >
            <i class="bi bi-plus"></i> {{ $t('combos.form.addExercise') }}
          </button>
        </div>
      </div>

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

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

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

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

.form-sub-group {
  padding-left: 24px;
}

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

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

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

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

.exercise-order-title {
  flex: 1;
  font-size: 14px;
}

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

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

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

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

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

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

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

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

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

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