<script setup>
import { getImageAltAttribute, getImageDefaultAltLabel } from '../../lib/markdown-image.js'

const props = defineProps({
  /** 패널 표시 여부 */
  open: {
    type: Boolean,
    default: false
  },
  /** 활성 블록 컨텍스트 */
  panel: {
    type: Object,
    default: null
  }
})

const emit = defineEmits([
  'panel-focus-in',
  'panel-focus-out',
  'update-media-image',
  'set-media-use-alt',
  'move-gallery-image',
  'remove-media-image',
  'add-gallery-images',
  'update-embed-url'
])

/**
 * 블록 종류 라벨
 * @returns {string}
 */
const panelTitle = computed(() => {
  if (!props.panel) {
    return ''
  }

  if (props.panel.kind === 'gallery') {
    return '갤러리'
  }

  if (props.panel.kind === 'embed') {
    return '임베드'
  }

  return '이미지'
})

/**
 * 블록 종류 부제
 * @returns {string}
 */
const panelMeta = computed(() => {
  if (!props.panel) {
    return ''
  }

  if (props.panel.kind === 'gallery') {
    return `${props.panel.images.length}개 이미지`
  }

  if (props.panel.kind === 'embed') {
    return 'YouTube·X 등 URL'
  }

  return '커서가 위치한 이미지 줄'
})

/**
 * 포커스가 패널 밖으로 나갔을 때만 이탈 이벤트를 보낸다.
 * @param {FocusEvent} event - focusout 이벤트
 * @returns {void}
 */
const onPanelFocusOut = (event) => {
  const root = event.currentTarget
  const next = event.relatedTarget

  if (next instanceof Node && root.contains(next)) {
    return
  }

  emit('panel-focus-out')
}
</script>

<template>
  <aside
    class="admin-editor-block-panel absolute inset-0 z-20 flex flex-col bg-white shadow-[-8px_0_24px_rgba(15,23,42,0.08)] transition-transform duration-300 ease-out"
    :class="open ? 'translate-x-0' : 'translate-x-full pointer-events-none'"
    :aria-hidden="!open"
    @focusin="emit('panel-focus-in')"
    @focusout="onPanelFocusOut"
  >
    <div v-if="panel" class="admin-editor-block-panel__inner flex h-full flex-col">
      <header class="admin-editor-block-panel__header flex h-[56px] shrink-0 items-center justify-between border-b border-[#e3e6e8] px-6">
        <div>
          <h2 class="admin-editor-block-panel__title text-xl font-bold text-black">
            {{ panelTitle }}
          </h2>
          <p class="admin-editor-block-panel__meta mt-1 text-xs text-[#6b7280]">
            {{ panelMeta }}
          </p>
        </div>
        <button
          v-if="panel.kind === 'gallery'"
          class="admin-editor-block-panel__add rounded bg-[#15171a] px-3 py-1.5 text-xs font-semibold text-white"
          type="button"
          @click="emit('add-gallery-images')"
        >
          이미지 추가
        </button>
      </header>

      <div class="admin-editor-block-panel__body flex-1 overflow-y-auto px-6 py-6">
        <template v-if="panel.kind === 'embed'">
          <label class="admin-editor-block-panel__field grid gap-2 text-sm">
            <span class="font-semibold text-[#394047]">임베드 URL</span>
            <input
              class="rounded border border-[#d7dde2] bg-[#eff1f2] px-3 py-2 text-sm text-[#15171a] outline-none transition-colors focus:border-[#8e9cac]"
              :value="panel.url"
              type="url"
              placeholder="https://www.youtube.com/watch?v=..."
              @input="emit('update-embed-url', $event.target.value)"
            >
          </label>
          <p class="admin-editor-block-panel__hint mt-3 text-xs leading-relaxed text-[#8e9cac]">
            YouTube·YouTube Shorts, X(트위터) 게시물 URL을 지원합니다. 그 외 URL은 링크 카드로 표시됩니다.
          </p>
        </template>

        <template v-else>
          <div class="admin-editor-block-panel__media-list grid gap-3">
            <div
              v-for="(image, imageIndex) in panel.images"
              :key="`block-panel-image-${imageIndex}`"
              class="admin-editor-block-panel__media-row grid gap-3 rounded border border-[#edf0f2] bg-[#fafafa] p-3"
            >
              <img
                class="aspect-[16/10] w-full rounded bg-[#eff1f2] object-cover"
                :src="image.url"
                :alt="getImageAltAttribute(image)"
              >
              <div class="grid gap-2">
                <label class="grid gap-1 text-xs font-semibold text-[#394047]">
                  캡션
                  <input
                    class="rounded border border-[#d7dde2] bg-white px-3 py-2 text-sm font-normal text-[#15171a] placeholder:font-normal placeholder:text-[#8e9cac]"
                    :value="image.caption || ''"
                    type="text"
                    placeholder="비우면 표시하지 않음"
                    @input="emit('update-media-image', imageIndex, { caption: $event.target.value })"
                  >
                </label>
                <div class="flex flex-wrap items-center justify-between gap-2">
                  <label class="inline-flex cursor-pointer items-center gap-2 text-xs font-semibold text-[#394047]">
                    <input
                      class="size-3.5 rounded border-[#c8ced3] text-[#15171a]"
                      type="checkbox"
                      :checked="image.useAlt"
                      @change="emit('set-media-use-alt', imageIndex, $event.target.checked)"
                    >
                    파일명을 대체 텍스트로 사용
                  </label>
                </div>
                <p
                  v-if="image.useAlt"
                  class="text-[11px] font-normal text-[#8e9cac]"
                >
                  {{ getImageDefaultAltLabel(image.url) || '(파일명 없음)' }}
                </p>
                <label class="grid gap-1 text-xs font-semibold text-[#394047]">
                  이미지 URL
                  <input
                    class="rounded border border-[#d7dde2] bg-white px-3 py-2 text-sm font-normal text-[#15171a]"
                    :value="image.url"
                    type="text"
                    @input="emit('update-media-image', imageIndex, { url: $event.target.value })"
                  >
                </label>
                <div v-if="panel.kind === 'gallery'" class="flex flex-wrap gap-2">
                  <button
                    class="rounded px-2.5 py-1.5 text-xs font-semibold text-[#394047] hover:bg-[#eff1f2] disabled:opacity-40"
                    type="button"
                    :disabled="imageIndex === 0"
                    @click="emit('move-gallery-image', imageIndex, -1)"
                  >
                    위로
                  </button>
                  <button
                    class="rounded px-2.5 py-1.5 text-xs font-semibold text-[#394047] hover:bg-[#eff1f2] disabled:opacity-40"
                    type="button"
                    :disabled="imageIndex === panel.images.length - 1"
                    @click="emit('move-gallery-image', imageIndex, 1)"
                  >
                    아래로
                  </button>
                  <button
                    class="rounded px-2.5 py-1.5 text-xs font-semibold text-red-600 hover:bg-red-50"
                    type="button"
                    @click="emit('remove-media-image', imageIndex)"
                  >
                    삭제
                  </button>
                </div>
                <button
                  v-else
                  class="rounded px-2.5 py-1.5 text-xs font-semibold text-red-600 hover:bg-red-50"
                  type="button"
                  @click="emit('remove-media-image', imageIndex)"
                >
                  삭제
                </button>
              </div>
            </div>
          </div>
        </template>
      </div>
    </div>
  </aside>
</template>
