<template>
  <aside class="shadowing-transcript flex h-full min-h-0 w-full flex-col border-l border-[var(--border)] bg-[var(--bg-surface)]">
    <div class="flex shrink-0 items-center justify-between gap-2 border-b border-[var(--border)] px-4 py-3">
      <span class="sh-panel-title">Bản chép</span>
      <label class="flex cursor-pointer items-center gap-1 text-[10px] font-semibold text-[var(--ink3)]">
        <input
          type="checkbox"
          class="rounded border-[var(--border)] text-[var(--spotify-green)]"
          :checked="showTranslation"
          @change="$emit('update:showTranslation', $event.target.checked)"
        />
        Trans
      </label>
    </div>

    <div ref="listEl" class="min-h-0 flex-1 overflow-y-auto p-3">
      <div
        v-for="(seg, idx) in segments"
        :key="seg.id"
        :ref="(el) => setCardRef(el, idx)"
        class="sh-transcript-card mb-2 w-full rounded-xl border border-[var(--border)] bg-[var(--bg-surface)] px-3 py-3 text-left transition-colors"
        :class="{ 'is-active': idx === activeIndex }"
      >
        <div class="mb-2 flex items-center justify-between">
          <button
            type="button"
            class="rounded-md px-2 py-0.5 text-[10px] font-bold"
            :class="idx === activeIndex ? 'bg-[var(--green-l)] text-black' : 'bg-[var(--bg-interactive)] text-[var(--ink3)]'"
            @click="$emit('seek', idx)"
          >
            #{{ seg.id }}
          </button>
          <button
            type="button"
            class="flex h-7 w-7 items-center justify-center rounded-lg text-gray-400 hover:bg-amber-50"
            :class="flaggedIds.includes(seg.id) ? '!text-amber-600' : ''"
            title="Đánh dấu câu khó"
            @click.stop="$emit('toggle-flag', seg.id)"
          >
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z"/>
              <line x1="4" y1="22" x2="4" y2="15"/>
            </svg>
          </button>
        </div>

        <div
          role="button"
          tabindex="0"
          class="sh-transcript-body w-full cursor-pointer text-left"
          @click="$emit('seek', idx)"
          @keydown.enter="$emit('seek', idx)"
        >
          <p v-if="dictationMode" class="m-0 break-words text-[13px] leading-[1.65] text-black">
            <span
              v-for="(w, wi) in wordsOf(seg)"
              :key="wi"
              class="inline align-baseline"
            >
              <button
                v-if="!isWordRevealed(seg.id, wi)"
                type="button"
                class="mr-0.5 inline-flex h-4 w-4 align-middle items-center justify-center text-[var(--ink3)] hover:text-[var(--spotify-green)]"
                title="Hiện từ"
                @click.stop="$emit('reveal-word', seg.id, wi)"
              >
                <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                  <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/>
                </svg>
              </button>
              <span :class="isWordRevealed(seg.id, wi) ? '' : 'text-gray-400'">
                {{ isWordRevealed(seg.id, wi) ? w : dotsFor(w) }}
              </span>
              <span v-if="wi < wordsOf(seg).length - 1">&nbsp;</span>
            </span>
          </p>
          <template v-else>
            <ShadowingVocabText
              v-if="vocabEnabled"
              class="sh-transcript-prose"
              :text="seg.text"
              :vocab-enabled="true"
              :source-quiz-id="sourceQuizId"
            />
            <p v-else class="m-0 break-words text-[13px] leading-[1.65] text-black">{{ seg.text }}</p>
          </template>
          <p
            v-if="showTranslation && seg.translation"
            class="mt-2 break-words text-[12px] leading-[1.55] text-gray-600"
          >
            {{ seg.translation }}
          </p>
        </div>
      </div>
    </div>
  </aside>
</template>

<script setup>
import { ref, watch, nextTick } from 'vue'
import { tokenizeWords } from '@/utils/segmentUtils.js'
import ShadowingVocabText from '@/components/shadowing/ShadowingVocabText.vue'

const props = defineProps({
  segments: { type: Array, default: () => [] },
  activeIndex: { type: Number, default: 0 },
  showTranslation: { type: Boolean, default: true },
  flaggedIds: { type: Array, default: () => [] },
  dictationMode: { type: Boolean, default: false },
  /** @type {Set<string> | string[]} keys `${segId}-${wi}` */
  revealedWordKeys: { type: [Set, Array], default: () => new Set() },
  vocabEnabled: { type: Boolean, default: true },
  sourceQuizId: { type: String, default: '' },
})

defineEmits(['seek', 'toggle-flag', 'update:showTranslation', 'reveal-word'])

const listEl = ref(null)
const cardRefs = ref({})

function setCardRef(el, idx) {
  if (el) cardRefs.value[idx] = el
}

function wordsOf(seg) {
  return tokenizeWords(seg?.text || '')
}

function wordKey(segId, wi) {
  return `${segId}-${wi}`
}

function isWordRevealed(segId, wi) {
  const keys = props.revealedWordKeys
  if (keys instanceof Set) return keys.has(wordKey(segId, wi))
  return (keys || []).includes(wordKey(segId, wi))
}

function dotsFor(w) {
  return '•'.repeat(Math.max(3, Math.min(8, w.length)))
}

/** Scroll active card to a fixed anchor — keep full card visible below scroll top. */
const SCROLL_ANCHOR_PX = 132

function scrollActiveToAnchor(idx) {
  const el = cardRefs.value[idx]
  const container = listEl.value
  if (!el || !container) return
  const containerRect = container.getBoundingClientRect()
  const elRect = el.getBoundingClientRect()
  const delta = elRect.top - containerRect.top - SCROLL_ANCHOR_PX
  if (Math.abs(delta) < 2) return
  container.scrollBy({ top: delta, behavior: 'smooth' })
}

watch(
  () => props.activeIndex,
  async (idx) => {
    await nextTick()
    scrollActiveToAnchor(idx)
  },
)
</script>
