<script setup lang="ts">
import { Splide, SplideSlide } from '@splidejs/vue-splide'
import type { Splide as SplideType, Options } from '@splidejs/splide'
import type {
  PageDataTemplateComponentSet,
  PageDataResourceGroups,
} from '#layers/types/api/pageData'
import { useSplideArrow } from '#layers/composables/useSplideArrow'

interface Props {
  slideData: PageDataTemplateComponentSet[]
  paginationData?: PageDataResourceGroups
  variant?: 'default' | 'media'
  drag?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  variant: 'default',
  drag: true,
})

const emit = defineEmits(['mounted', 'move', 'arrowClick'])

// Splide 화살표 로직을 위한 composable 사용
const { addArrowClickListeners } = useSplideArrow()

let mainInst: SplideType | null = null
let thumbsInst: SplideType | null = null

defineExpose({
  mainInst: computed(() => mainInst),
  thumbsInst: computed(() => thumbsInst),
})

const mainRef = ref<InstanceType<typeof Splide> | null>(null)
const thumbsRef = ref<InstanceType<typeof Splide> | null>(null)

const mainOptions = computed<Options>(() => ({
  type: 'fade',
  rewind: true,
  perPage: 1,
  perMove: 1,
  speed: 500,
  arrows: false,
  pagination: false,
  drag: props.drag,
}))

const thumbOptions = computed<Options>(() => ({
  type: 'slide',
  rewind: true,
  autoWidth: true,
  perMove: 1,
  arrows: true,
  pagination: false,
  isNavigation: true,
  updateOnMove: true,
  classes: {
    arrows: 'splide-arrows',
    arrow: 'splide-arrow',
    prev: 'arrow-prev',
    next: 'arrow-next',
  },
  breakpoints: {
    [BREAKPOINTS.md - 1]: {
      padding: {
        left: 40,
        right: 40,
      },
    },
    [BREAKPOINTS.sm - 1]: {
      padding: {
        left: 20,
        right: 20,
      },
    },
  },
}))

const getThumbnailSrc = (item: PageDataTemplateComponentSet) => {
  if (props.variant === 'media') {
    const mediaComponent = getComponentGroup(item, 'media')
    return mediaComponent ? getMediaImgSrc(mediaComponent) : ''
  }

  const thumbnailComponent = getComponentGroup(item, 'pagenaviThumbnail')
  const thumbnailPath = getDeviceSrc(thumbnailComponent?.res_path)

  return thumbnailPath?.pcSrc
}

const handleMove = (
  splide: SplideType,
  newIndex: number,
  oldIndex: number,
  destIndex: number
) => {
  emit('move', splide, newIndex, oldIndex, destIndex)
}

const handleSplideMounted = (splide: SplideType) => {
  emit('mounted', splide)
}

onMounted(() => {
  mainInst = mainRef.value?.splide ?? null
  thumbsInst = thumbsRef.value?.splide ?? null

  if (mainInst && thumbsInst) {
    mainInst.sync(thumbsInst)
    // 썸네일 슬라이드의 화살표 버튼에 이벤트 리스너 추가
    nextTick(() => {
      addArrowClickListeners(thumbsInst, (direction, targetIndex) => {
        emit('arrowClick', direction, targetIndex)
      })
    })
  }
})

onBeforeUnmount(() => {
  mainInst?.destroy?.()
  thumbsInst?.destroy?.()
})
</script>

<template>
  <div :class="['thumbnail-carousel', $attrs?.class, `thumbnail-${variant}`]">
    <!-- 메인 슬라이드 -->
    <Splide
      ref="mainRef"
      :options="mainOptions"
      class="main-splide"
      @splide:move="handleMove"
      @splide:mounted="handleSplideMounted"
    >
      <slot />
    </Splide>
    <!-- 썸네일 슬라이드 -->
    <Splide
      v-if="props.slideData.length > 0"
      ref="thumbsRef"
      :options="thumbOptions"
      class="thumbnail-splide"
      :style="getPaginationClass(paginationData)"
    >
      <SplideSlide
        v-for="(item, index) in props.slideData"
        :key="item.set_order || index"
        class="thumbnail-slide"
      >
        <img
          :src="getThumbnailSrc(item)"
          alt="thumbnail image"
          class="slide-image"
        />
      </SplideSlide>
    </Splide>
  </div>
</template>

<style scoped>
.thumbnail-carousel {
}
.thumbnail-carousel:deep(img) {
  @apply w-full h-full object-cover;
}
.thumbnail-splide {
  @apply overflow-hidden flex justify-center;
}
.thumbnail-splide:deep(.splide__track) {
  @apply md:w-[calc(100%-16px)];
}
.thumbnail-slide {
  @apply overflow-hidden relative mr-[12px] !border-none rounded-[4px] bg-[var(--pagination-disabled)] md:mr-[16px]
  after:content-[''] after:absolute after:top-0 after:left-0 after:w-full after:h-full after:border after:rounded-[4px];
}
.thumbnail-slide:hover,
.thumbnail-slide.is-active {
  @apply bg-[var(--pagination-active)];
}
.thumbnail-slide::after {
  @apply border-[var(--pagination-disabled)];
}
.thumbnail-slide:hover::after,
.thumbnail-slide.is-active::after {
  @apply border-[var(--pagination-active)];
}

/* 기본 버전 스타일 */
.thumbnail-carousel.thumbnail-default,
.thumbnail-carousel.thumbnail-default .main-splide,
.thumbnail-carousel.thumbnail-default .main-splide:deep(.splide__track) {
  @apply h-full;
}
.thumbnail-carousel.thumbnail-default .thumbnail-splide {
  @apply absolute bottom-[32px] left-1/2 -translate-x-1/2 max-w-[100%] md:bottom-[48px] md:max-w-[896px] md:px-[64px];
}
.thumbnail-carousel.thumbnail-default:deep(.arrow-prev) {
  @apply left-0;
}
.thumbnail-carousel.thumbnail-default:deep(.arrow-next) {
  @apply right-0;
}
.thumbnail-carousel.thumbnail-default .thumbnail-slide {
  @apply aspect-[1/1] w-[8px] md:w-[80px]
  after:hidden md:after:block;
}
.thumbnail-carousel.thumbnail-default .thumbnail-slide:hover img,
.thumbnail-carousel.thumbnail-default .thumbnail-slide.is-active img {
  @apply md:grayscale-0;
}
.thumbnail-carousel.thumbnail-default .thumbnail-slide img {
  @apply hidden md:block md:grayscale;
}

/* 미디어 버전 스타일 */
.thumbnail-carousel.thumbnail-media {
  @apply flex flex-col items-center;
}
.thumbnail-carousel.thumbnail-media .thumbnail-splide {
  @apply max-w-[calc(100%+40px)] mt-[20px] mx-[-20px] 
  sm:max-w-[calc(100%+80px)] sm:mx-[-40px] 
  md:max-w-[100%] md:mt-[28px] md:mx-auto md:px-[64px];
}
.thumbnail-carousel.thumbnail-media:deep(.arrow-prev) {
  @apply left-[0];
}
.thumbnail-carousel.thumbnail-media:deep(.arrow-next) {
  @apply right-[0];
}
.thumbnail-carousel.thumbnail-media .thumbnail-slide {
  @apply aspect-[16/9] w-[92px] md:w-[128px];
}
</style>
