<script setup lang="ts">
const props = defineProps<{
  message: string
  visible: boolean
}>()

const emit = defineEmits<{
  close: []
  skip: []
}>()

const { t } = useI18n()
const progressionStore = useProgressionStore()

const messageRef = computed(() => props.message)
const { displayedText, isTyping, skip, start } = useTypewriter(messageRef, {
  speed: 40,
})

const bugImages: Record<number, string> = {
  1: '/images/bug/bug-stage-1.svg',
  2: '/images/bug/bug-stage-2.svg',
  3: '/images/bug/bug-stage-3.svg',
  4: '/images/bug/bug-stage-4.svg',
  5: '/images/bug/bug-stage-5.svg',
}

const currentBugImage = computed(() => {
  return bugImages[progressionStore.narratorStage] || bugImages[1]
})

watch(
  () => props.visible,
  (newVisible) => {
    if (newVisible && props.message) {
      start()
    }
  },
  { immediate: true },
)

watch(
  () => props.message,
  (newMessage) => {
    if (newMessage && props.visible) {
      start()
    }
  },
)

function handleInteraction() {
  if (isTyping.value) {
    skip()
    emit('skip')
  }
}

function handleKeydown(e: KeyboardEvent) {
  if (e.code === 'Space' || e.code === 'Enter') {
    e.preventDefault()
    handleInteraction()
  }
  if (e.code === 'Escape') {
    emit('close')
  }
}
</script>

<template>
  <Transition name="narrator-slide">
    <div
      v-if="visible"
      class="narrator-bubble fixed bottom-4 left-4 right-4 md:left-auto md:right-8 md:max-w-md z-50"
      role="status"
      aria-live="polite"
      tabindex="0"
      @click="handleInteraction"
      @keydown="handleKeydown"
    >
      <div
        class="flex items-start gap-4 bg-sky-dark-50 rounded-xl p-4 shadow-xl border border-sky-dark-100"
      >
        <div class="shrink-0 w-16 h-16 md:w-20 md:h-20">
          <img
            :src="currentBugImage"
            :alt="t('narrator.bugAlt', { stage: progressionStore.narratorStage })"
            class="w-full h-full object-contain"
          />
        </div>

        <div class="flex-1 min-w-0">
          <p class="font-narrative text-sky-text text-base md:text-lg leading-relaxed">
            {{ displayedText }}
            <span
              v-if="isTyping"
              class="inline-block w-0.5 h-5 bg-sky-accent animate-blink ml-0.5"
              aria-hidden="true"
            />
          </p>

          <span class="sr-only">{{ message }}</span>

          <p v-if="isTyping" class="text-xs text-sky-text-muted mt-2 font-ui">
            {{ t('narrator.clickToSkip') }}
          </p>
        </div>

        <button
          type="button"
          class="shrink-0 p-1 text-sky-text-muted hover:text-sky-text transition-colors"
          :aria-label="t('common.close')"
          @click.stop="emit('close')"
        >
          <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path
              stroke-linecap="round"
              stroke-linejoin="round"
              stroke-width="2"
              d="M6 18L18 6M6 6l12 12"
            />
          </svg>
        </button>
      </div>
    </div>
  </Transition>
</template>

<style scoped>
.narrator-slide-enter-active,
.narrator-slide-leave-active {
  transition: all 0.3s ease;
}

.narrator-slide-enter-from {
  opacity: 0;
  transform: translateY(20px);
}

.narrator-slide-leave-to {
  opacity: 0;
  transform: translateY(10px);
}

@keyframes blink {
  0%,
  50% {
    opacity: 1;
  }
  51%,
  100% {
    opacity: 0;
  }
}

.animate-blink {
  animation: blink 1s infinite;
}

@media (max-width: 767px) {
  .narrator-bubble {
    bottom: calc(var(--bottom-bar-height, 64px) + 1rem);
  }
}

@media (prefers-reduced-motion: reduce) {
  .narrator-slide-enter-active,
  .narrator-slide-leave-active {
    transition: opacity 0.15s ease;
    transform: none;
  }

  .narrator-slide-enter-from,
  .narrator-slide-leave-to {
    transform: none;
  }

  .animate-blink {
    animation: none;
    opacity: 1;
  }
}
</style>
