<script setup>
import { ref, watch, onMounted, onUnmounted } from 'vue'
import { useRouter, useRoute, onBeforeRouteLeave } from 'vue-router'
import { useTranslation } from 'i18next-vue'
import { useSessionExecution } from '../composables/useSessionExecution.js'
import { useMediaSession } from '../composables/useMediaSession.js'
import { exerciseRepository } from '../db/repositories/exerciseRepository.js'
import { useOnlineStatus } from '../composables/useOnlineStatus.js'
import { renderMarkdown } from '../utils/markdown.js'
import { getYouTubeId } from '../utils/youtube.js'
import TimerDisplay from '../components/TimerDisplay.vue'

const { t } = useTranslation()
const route = useRoute()
const router = useRouter()
const sessionId = route.params.id
const { isOnline } = useOnlineStatus()

const {
  sessionTitle,
  currentIndex,
  totalSteps,
  currentStep,
  nextStep,
  showFinalRound,
  sessionDone,
  loading,
  error,
  currentReps,
  currentWeight,
  currentSide,
  timerPhase,
  timerRemaining,
  timerPaused,
  timerActive,
  isAmrapTimeUp,
  init,
  markDone,
  continueAfterCombo,
  continueAfterAmrap,
  addOneMoreRound,
  togglePause,
  goBack,
  exit,
} = useSessionExecution(sessionId)

const {
  start: startMediaSession,
  updateMetadata: updateMediaMetadata,
  setPlaybackState: setMediaPlaybackState,
  stop: stopMediaSession,
} = useMediaSession()

const showDetail = ref(false)
const detailExercise = ref(null)
const detailLoading = ref(false)
const detailPausedTimer = ref(false)

watch(currentStep, (step) => {
  showDetail.value = false
  detailExercise.value = null
  detailPausedTimer.value = false
  updateMediaMetadata(step, sessionTitle.value)
})

watch(sessionDone, (done) => {
  if (done) stopMediaSession()
})

async function toggleDetail() {
  showDetail.value = !showDetail.value
  if (showDetail.value) {
    if (timerActive.value && !timerPaused.value) {
      togglePause()
      detailPausedTimer.value = true
    }
    if (!detailExercise.value && currentStep.value) {
      detailLoading.value = true
      detailExercise.value = await exerciseRepository.getById(currentStep.value.exerciseId)
      detailLoading.value = false
    }
  } else {
    if (detailPausedTimer.value) {
      togglePause()
      detailPausedTimer.value = false
    }
  }
}

function onMediaPlayPause() {
  if (!timerActive.value) return
  togglePause()
  setMediaPlaybackState(timerPaused.value ? 'paused' : 'playing')
}

function onMediaNext() {
  if (sessionDone.value) return
  if (isAmrapTimeUp.value) {
    onContinueAmrap()
  } else if (showFinalRound.value) {
    onContinue()
  } else if (timerPhase.value !== 'rest') {
    onDone()
  }
}

function onMediaPrevious() {
  goBack()
}

function onMediaStop() {
  onExit()
}

onMounted(async () => {
  await init()
  if (!error.value) {
    startMediaSession({
      onPlayPause: onMediaPlayPause,
      onNext: onMediaNext,
      onPrevious: onMediaPrevious,
      onStop: onMediaStop,
    })
  }
})

onUnmounted(() => {
  stopMediaSession()
})

onBeforeRouteLeave(async () => {
  if (!sessionDone.value) {
    const confirmed = window.confirm(t('execution.leaveConfirm'))
    if (!confirmed) return false
    await exit()
  }
})

function toggleSide() {
  currentSide.value = currentSide.value === 'left' ? 'right' : 'left'
}

async function onExit() {
  await exit()
  router.push({ name: 'session-detail', params: { id: sessionId } })
}

async function onDone() {
  await markDone()
  if (sessionDone.value) {
    router.push({ name: 'session-detail', params: { id: sessionId } })
  }
}

async function onContinue() {
  await continueAfterCombo()
  if (sessionDone.value) {
    router.push({ name: 'session-detail', params: { id: sessionId } })
  }
}

async function onContinueAmrap() {
  await continueAfterAmrap()
  if (sessionDone.value) {
    router.push({ name: 'session-detail', params: { id: sessionId } })
  }
}
</script>

<template>
  <Teleport to="#actionbar-actions" defer>
    <button
      data-testid="execute-exit-btn"
      :title="$t('execution.exit')"
      :aria-label="$t('execution.exit')"
      @click="onExit"
    >
      <i class="bi bi-x-lg"></i>
    </button>
  </Teleport>

  <div class="session-execute-view">
    <p v-if="loading" class="text-muted">{{ $t('app.loading') }}</p>
    <p v-else-if="error" class="text-danger">{{ error }}</p>

    <template v-else>
      <!-- Session title -->
      <h2 data-testid="execute-session-title">{{ sessionTitle }}</h2>

      <!-- Progress bar -->
      <div class="progress-section" data-testid="execute-progress">
        <div
          class="progress-bar-track"
          role="progressbar"
          :aria-valuenow="currentIndex"
          aria-valuemin="0"
          :aria-valuemax="totalSteps"
          :aria-label="currentIndex + ' / ' + totalSteps + ' ' + $t('execution.steps')"
        >
          <div
            class="progress-bar-fill"
            :style="{ width: totalSteps > 0 ? (currentIndex / totalSteps) * 100 + '%' : '0%' }"
          ></div>
        </div>
        <span class="progress-label" data-testid="execute-progress-label">
          {{ currentIndex }} / {{ totalSteps }} {{ $t('execution.steps') }}
        </span>
      </div>

      <!-- AMRAP time-up screen -->
      <div v-if="isAmrapTimeUp" class="final-round-card card" data-testid="execute-amrap-timeup">
        <div class="final-round-message">
          <i class="bi bi-stopwatch-fill"></i>
          {{ $t('execution.timer.timeUpTitle', { title: currentStep?.comboTitle }) }}
        </div>
        <div class="final-round-actions">
          <button
            class="btn btn-primary"
            data-testid="execute-amrap-continue-btn"
            @click="onContinueAmrap"
          >
            {{ $t('execution.continue') }} →
          </button>
        </div>
      </div>

      <!-- TABATA rest screen -->
      <div
        v-else-if="timerPhase === 'rest'"
        class="rest-card card"
        data-testid="execute-tabata-rest"
      >
        <div class="rest-label">{{ $t('execution.timer.rest') }}</div>
        <p v-if="nextStep" class="rest-next text-muted">
          {{ $t('execution.timer.nextExercise') }} {{ nextStep.exerciseTitle }}
        </p>
        <TimerDisplay
          :remaining="timerRemaining"
          :is-paused="timerPaused"
          :pause-label="$t('execution.timer.pause')"
          :resume-label="$t('execution.timer.resume')"
          @toggle-pause="togglePause"
        />
      </div>

      <!-- Final-round screen -->
      <div
        v-else-if="showFinalRound"
        class="final-round-card card"
        data-testid="execute-final-round"
      >
        <div class="final-round-message">
          <i class="bi bi-check-circle-fill"></i>
          {{
            $t('execution.comboComplete', {
              title: currentStep?.comboTitle,
              rounds: currentStep?.roundNumber,
            })
          }}
        </div>
        <div class="final-round-actions">
          <button class="btn btn-primary" data-testid="execute-continue-btn" @click="onContinue">
            {{ $t('execution.continue') }} →
          </button>
          <button
            class="btn btn-secondary"
            data-testid="execute-one-more-btn"
            @click="addOneMoreRound"
          >
            + {{ $t('execution.oneMoreRound') }}
          </button>
        </div>
      </div>

      <!-- Current step -->
      <template v-else-if="currentStep">
        <div class="step-label">▶ {{ $t('execution.now') }}</div>
        <div class="step-card card" data-testid="execute-current-step">
          <h3>
            <button
              class="exercise-title-btn"
              :aria-expanded="showDetail"
              :aria-label="showDetail ? $t('execution.hideDetails') : $t('execution.showDetails')"
              @click="toggleDetail"
            >
              <span data-testid="execute-exercise-title">{{ currentStep.exerciseTitle }}</span>
              <i
                :class="showDetail ? 'bi bi-chevron-up' : 'bi bi-chevron-down'"
                class="detail-chevron"
              ></i>
            </button>
          </h3>

          <!-- Exercise detail panel -->
          <div
            v-if="showDetail"
            class="exercise-detail-panel"
            data-testid="execute-exercise-detail"
          >
            <p v-if="detailLoading" class="text-muted detail-loading">{{ $t('app.loading') }}</p>
            <template v-else-if="detailExercise">
              <div
                v-if="detailExercise.description"
                class="detail-description"
                v-html="renderMarkdown(detailExercise.description)"
              />
              <div
                v-if="detailExercise.image_urls && detailExercise.image_urls.length"
                class="detail-images"
              >
                <img
                  v-for="(url, i) in detailExercise.image_urls"
                  :key="'img-' + i"
                  :src="url"
                  :alt="currentStep.exerciseTitle + ' image ' + (i + 1)"
                  class="detail-image"
                  loading="lazy"
                  @error="($event) => ($event.target.style.display = 'none')"
                />
              </div>
              <div
                v-if="detailExercise.video_urls && detailExercise.video_urls.length"
                class="detail-videos"
              >
                <p v-if="!isOnline" class="detail-offline text-muted">
                  <i class="bi bi-wifi-off"></i> {{ $t('execution.videoOffline') }}
                </p>
                <template v-else>
                  <a
                    v-for="(url, i) in detailExercise.video_urls"
                    :key="'vid-' + i"
                    :href="url"
                    target="_blank"
                    rel="noopener noreferrer"
                    class="detail-video-link"
                  >
                    <template v-if="getYouTubeId(url)">
                      <img
                        :src="'https://img.youtube.com/vi/' + getYouTubeId(url) + '/mqdefault.jpg'"
                        :alt="currentStep.exerciseTitle + ' video ' + (i + 1)"
                        class="detail-yt-thumb"
                        loading="lazy"
                      />
                    </template>
                    <template v-else> <i class="bi bi-play-circle"></i> {{ url }} </template>
                  </a>
                </template>
              </div>
            </template>
          </div>

          <!-- Combo context -->
          <p
            v-if="currentStep.comboId"
            class="combo-context text-muted"
            data-testid="execute-combo-context"
          >
            {{
              $t('execution.comboContext', {
                title: currentStep.comboTitle,
                round: currentStep.roundNumber,
                total: currentStep.totalRounds,
              })
            }}
          </p>

          <!-- Timer display (EMOM, TABATA work, AMRAP) -->
          <TimerDisplay
            v-if="timerActive && timerPhase !== 'rest'"
            :remaining="timerRemaining"
            :is-paused="timerPaused"
            :pause-label="$t('execution.timer.pause')"
            :resume-label="$t('execution.timer.resume')"
            data-testid="execute-timer"
            @toggle-pause="togglePause"
          />

          <div class="step-inputs">
            <!-- Reps input -->
            <div class="input-row">
              <label class="input-label">{{ $t('execution.reps') }}</label>
              <div class="stepper">
                <button
                  class="stepper-btn btn-primary"
                  :aria-label="'-1 ' + $t('execution.reps')"
                  @click="currentReps = Math.max(0, currentReps - 1)"
                >
                  <i class="bi bi-dash-circle-fill"></i>
                </button>
                <input
                  type="number"
                  class="step-input"
                  data-testid="execute-reps-input"
                  :value="currentReps"
                  min="0"
                  @input="currentReps = Number($event.target.value)"
                />
                <button
                  class="stepper-btn btn-primary"
                  :aria-label="'+1 ' + $t('execution.reps')"
                  @click="currentReps++"
                >
                  <i class="bi bi-plus-circle-fill"></i>
                </button>
                <button
                  class="stepper-btn stepper-btn-fast"
                  :aria-label="'+5 ' + $t('execution.reps')"
                  @click="currentReps += 5"
                >
                  <i class="bi bi-forward-fill"></i>
                </button>
              </div>
            </div>

            <!-- Weight input -->
            <div class="input-row">
              <label class="input-label">{{ $t('execution.weight') }}</label>
              <div class="stepper">
                <button
                  class="stepper-btn btn-primary"
                  :aria-label="'-0.5 ' + $t('execution.weight')"
                  @click="currentWeight = Math.max(0, +(currentWeight - 0.5).toFixed(1))"
                >
                  <i class="bi bi-dash-circle-fill"></i>
                </button>
                <input
                  type="number"
                  class="step-input"
                  data-testid="execute-weight-input"
                  :value="currentWeight"
                  min="0"
                  step="0.5"
                  @input="currentWeight = Number($event.target.value)"
                />
                <button
                  class="stepper-btn btn-primary"
                  :aria-label="'+0.5 ' + $t('execution.weight')"
                  @click="currentWeight = +(currentWeight + 0.5).toFixed(1)"
                >
                  <i class="bi bi-plus-circle-fill"></i>
                </button>
                <button
                  class="stepper-btn stepper-btn-fast"
                  :aria-label="'+1 ' + $t('execution.weight')"
                  @click="currentWeight = +(currentWeight + 1).toFixed(1)"
                >
                  <i class="bi bi-forward-fill"></i>
                </button>
              </div>
              <span class="input-unit">kg</span>
            </div>

            <!-- Side toggle (asymmetric exercises only) -->
            <div v-if="currentStep.asymmetric" class="input-row">
              <label class="input-label">{{ $t('execution.side') }}</label>
              <button
                class="side-toggle"
                data-testid="execute-side-toggle"
                :aria-label="
                  $t('execution.side') +
                  ': ' +
                  (currentSide === 'left' ? $t('execution.sideLeft') : $t('execution.sideRight'))
                "
                @click="toggleSide"
              >
                {{ currentSide === 'left' ? $t('execution.sideLeft') : $t('execution.sideRight') }}
                ↔
              </button>
              <span class="asym-hint text-muted">
                {{
                  currentStep.alternate
                    ? $t('execution.asymAlternate', {
                        left: $t('execution.sideLeft'),
                        right: $t('execution.sideRight'),
                        count: Math.floor(currentReps / 2),
                      })
                    : $t('execution.asymSequential', {
                        left: $t('execution.sideLeft'),
                        right: $t('execution.sideRight'),
                        count: Math.floor(currentReps / 2),
                      })
                }}
              </span>
            </div>
          </div>

          <div class="step-actions">
            <button
              class="btn btn-secondary previous-btn"
              data-testid="execute-previous-btn"
              :disabled="currentIndex === 0"
              :title="$t('execution.previous')"
              :aria-label="$t('execution.previous')"
              @click="goBack"
            >
              <i class="bi bi-skip-start-fill"></i>
            </button>
            <button class="btn btn-primary done-btn" data-testid="execute-done-btn" @click="onDone">
              <i class="bi bi-check-lg"></i> {{ $t('execution.done') }}
            </button>
          </div>
        </div>

        <!-- Next step preview -->
        <template v-if="nextStep && timerPhase !== 'rest'">
          <div class="step-label next-label">↓ {{ $t('execution.next') }}</div>
          <div class="next-step-preview" data-testid="execute-next-step">
            <span class="next-title">{{ nextStep.exerciseTitle }}</span>
            <span class="next-detail text-muted">
              — {{ nextStep.prefillReps }} {{ $t('execution.reps') }}
              <template v-if="nextStep.comboId">
                ({{ nextStep.comboTitle }}, {{ $t('execution.round') }} {{ nextStep.roundNumber }})
              </template>
            </span>
          </div>
        </template>
      </template>

      <!-- Session complete -->
      <div v-else class="session-complete" data-testid="execute-complete">
        <i class="bi bi-trophy-fill complete-icon"></i>
        <p>{{ $t('execution.complete') }}</p>
        <button
          class="btn btn-primary"
          @click="$router.push({ name: 'session-detail', params: { id: sessionId } })"
        >
          {{ $t('execution.backToSession') }}
        </button>
      </div>
    </template>
  </div>
</template>

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

.session-execute-view h2 {
  font-size: 20px;
  font-weight: 600;
  margin-bottom: 12px;
}

/* Progress */
.progress-section {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 20px;
}

.progress-bar-track {
  flex: 1;
  height: 8px;
  background: var(--border-color);
  border-radius: 4px;
  overflow: hidden;
}

.progress-bar-fill {
  height: 100%;
  background: var(--btn-primary-bg);
  border-radius: 4px;
  transition: width 0.3s ease;
}

.progress-label {
  font-size: 13px;
  color: var(--color-text-muted);
  white-space: nowrap;
}

/* Step labels */
.step-label {
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-muted);
  margin-bottom: 6px;
}

.next-label {
  margin-top: 16px;
}

/* Current step card */
.step-card {
  padding: 16px;
  margin-bottom: 0;
}

.step-card h3 {
  font-size: 20px;
  font-weight: 700;
  margin-bottom: 4px;
}

.exercise-title-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  color: inherit;
  font-size: inherit;
  font-weight: inherit;
  text-align: left;
  width: 100%;
}

.exercise-title-btn:hover {
  opacity: 0.8;
}

.detail-chevron {
  font-size: 14px;
  flex-shrink: 0;
  color: var(--color-text-muted);
}

/* Exercise detail panel */
.exercise-detail-panel {
  margin: 8px 0 12px;
  padding: 10px 12px;
  border-radius: 8px;
  background: var(--color-surface, var(--front-color));
  border: 1px solid var(--border-color);
}

.detail-loading {
  font-size: 13px;
  margin: 0;
}

.detail-description {
  font-size: 14px;
  line-height: 1.5;
  margin-bottom: 8px;
}

.detail-description :deep(p) {
  margin: 0 0 6px;
}

.detail-description :deep(p:last-child) {
  margin-bottom: 0;
}

.detail-description :deep(ul),
.detail-description :deep(ol) {
  margin: 0 0 6px;
  padding-left: 18px;
}

.detail-description :deep(strong) {
  font-weight: 600;
}

.detail-images {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 8px;
}

.detail-image {
  width: 120px;
  height: 80px;
  object-fit: cover;
  border-radius: 6px;
  border: 1px solid var(--border-color);
}

.detail-videos {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 8px;
}

.detail-video-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--btn-primary-bg);
  text-decoration: none;
}

.detail-video-link:hover {
  opacity: 0.8;
}

.detail-yt-thumb {
  width: 160px;
  max-width: 100%;
  border-radius: 6px;
  border: 1px solid var(--border-color);
  display: block;
}

.detail-offline {
  font-size: 13px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 0;
}

.combo-context {
  font-size: 13px;
  margin-bottom: 12px;
}

/* Inputs */
.step-inputs {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 14px 0;
}

.input-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.input-label {
  width: 70px;
  font-size: 14px;
  font-weight: 500;
  flex-shrink: 0;
}

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

.stepper-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  font-size: 22px;
  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: 64px;
  padding: 6px 4px;
  border: 1px solid var(--border-color);
  border-radius: 6px;
  background: var(--color-background);
  color: var(--color-text);
  font-size: 18px;
  font-weight: 600;
  text-align: center;
}

/* hide native number spinners */
.step-input::-webkit-inner-spin-button,
.step-input::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.step-input[type='number'] {
  -moz-appearance: textfield;
}

.step-input:focus {
  outline: none;
  border-color: var(--btn-primary-bg);
}

.input-unit {
  font-size: 13px;
  color: var(--color-text-muted);
}

.asym-hint {
  font-size: 12px;
}

.side-toggle {
  padding: 6px 14px;
  border: 1px solid var(--btn-primary-bg);
  border-radius: 6px;
  background: var(--btn-primary-bg);
  color: var(--btn-primary-color);
  cursor: pointer;
  font-size: 14px;
  font-weight: 600;
}

.side-toggle:hover {
  opacity: 0.85;
}

.step-actions {
  display: flex;
  gap: 8px;
  margin-top: 4px;
}

.previous-btn {
  flex-shrink: 0;
  padding: 10px 14px;
  font-size: 16px;
}

.previous-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.done-btn {
  flex: 1;
  font-size: 16px;
  padding: 10px;
}

/* Next step */
.next-step-preview {
  font-size: 14px;
  padding: 10px 12px;
  background: var(--color-surface, var(--front-color));
  border-radius: 8px;
  border: 1px solid var(--border-color);
}

.next-title {
  font-weight: 600;
}

/* Final round / time-up */
.final-round-card {
  padding: 24px;
  text-align: center;
}

.final-round-message {
  font-size: 18px;
  font-weight: 600;
  margin-bottom: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  color: var(--btn-primary-bg);
}

.final-round-message i {
  font-size: 24px;
}

.final-round-actions {
  display: flex;
  gap: 12px;
  justify-content: center;
  flex-wrap: wrap;
}

/* TABATA rest screen */
.rest-card {
  padding: 24px;
  text-align: center;
}

.rest-label {
  font-size: 28px;
  font-weight: 800;
  letter-spacing: 0.1em;
  color: var(--btn-primary-bg);
  margin-bottom: 8px;
}

.rest-next {
  font-size: 14px;
  margin-bottom: 0;
}

/* Complete */
.session-complete {
  text-align: center;
  padding: 40px 20px;
}

.complete-icon {
  font-size: 48px;
  color: var(--btn-primary-bg);
  margin-bottom: 16px;
  display: block;
}

.session-complete p {
  font-size: 18px;
  font-weight: 600;
  margin-bottom: 20px;
}

/* Shared btn styles (mirror what's in layout.css) */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 18px;
  border-radius: 8px;
  border: none;
  cursor: pointer;
  font-size: 14px;
  font-weight: 500;
  transition: opacity 0.15s;
}

.btn:hover {
  opacity: 0.85;
}

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

.btn-secondary {
  background: var(--front-color2);
  color: var(--btn-primary-color);
}

.text-danger {
  color: var(--color-danger, #dc3545);
}
</style>
