<template>
  <section class="carousel-wrap">
    <div class="carousel-panel" :style="{ height: heightCss }">
      <ClientOnly>
        <a-carousel
          ref="carouselRef"
          class="carousel"
          :autoplay="autoplayEnabled"
          :autoplay-speed="autoplaySpeed"
          :dots="dotsEnabled"
          :effect="effect"
          :style="{ height: heightCss }"
        >
          <div
            v-for="(it, idx) in normalizedItems"
            :key="`${it.src}::${idx}`"
            class="carousel-item"
            :style="{ height: heightCss }"
          >
            <NuxtLink
              v-if="it.href && !isExternal(it.href)"
              :to="it.href"
              class="carousel-link"
              aria-label="carousel-slide"
            >
              <img class="carousel-img" :src="it.src" :alt="it.alt || 'slide'" loading="lazy" />
            </NuxtLink>
            <a
              v-else-if="it.href"
              class="carousel-link"
              :href="it.href"
              target="_blank"
              rel="noopener noreferrer"
              aria-label="carousel-slide"
            >
              <img class="carousel-img" :src="it.src" :alt="it.alt || 'slide'" loading="lazy" />
            </a>
            <img v-else class="carousel-img" :src="it.src" :alt="it.alt || 'slide'" loading="lazy" />
          </div>
        </a-carousel>

        <button
          v-if="showNav"
          type="button"
          class="carousel-nav carousel-nav-left"
          aria-label="prev"
          @click.prevent.stop="prev"
        >
          <span aria-hidden="true">&lsaquo;</span>
        </button>
        <button
          v-if="showNav"
          type="button"
          class="carousel-nav carousel-nav-right"
          aria-label="next"
          @click.prevent.stop="next"
        >
          <span aria-hidden="true">&rsaquo;</span>
        </button>

        <template #fallback>
          <img class="carousel-img" :style="{ height: heightCss }" :src="fallbackSrc" alt="slide" />
        </template>
      </ClientOnly>
    </div>
  </section>
</template>

<script setup lang="ts">
type CarouselItem = {
  src: string
  href?: string
  alt?: string
}

const props = withDefaults(
  defineProps<{
    items: CarouselItem[]
    height?: number | string
    autoplaySpeed?: number
    effect?: 'scrollx' | 'fade'
  }>(),
  {
    height: 360,
    autoplaySpeed: 4500,
    effect: 'fade'
  }
)

type AntdCarouselExpose = {
  next: () => void
  prev: () => void
  goTo: (slide: number, dontAnimate?: boolean) => void
}

const carouselRef = ref<AntdCarouselExpose | null>(null)

const heightCss = computed(() => (typeof props.height === 'number' ? `${props.height}px` : props.height))

const normalizedItems = computed(() => (props.items || []).filter((it) => it && typeof it.src === 'string' && it.src))

const autoplayEnabled = computed(() => normalizedItems.value.length > 1)
const dotsEnabled = computed(() => normalizedItems.value.length > 1)
const showNav = computed(() => normalizedItems.value.length > 1)

const fallbackSrc = computed(() => normalizedItems.value[0]?.src || '')

function isExternal(href: string) {
  return /^https?:\/\//i.test(href)
}

function next() {
  carouselRef.value?.next()
}

function prev() {
  carouselRef.value?.prev()
}
</script>

<style scoped>
.carousel-panel {
  background: #fff;
  position: relative;
  overflow: hidden;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.04);
}

.carousel {
  height: 100%;
}

.carousel-item {
  height: 100%;
}

.carousel-link {
  display: block;
  height: 100%;
}

.carousel-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.carousel :deep(.slick-list),
.carousel :deep(.slick-track),
.carousel :deep(.slick-slide),
.carousel :deep(.slick-slide > div) {
  height: 100%;
}

.carousel-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 5;
  width: 42px;
  height: 42px;
  border-radius: 9999px;
  border: 1px solid rgba(255, 255, 255, 0.55);
  background: rgba(0, 0, 0, 0.35);
  color: rgba(255, 255, 255, 0.95);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  user-select: none;
}

.carousel-nav:hover {
  background: rgba(0, 0, 0, 0.5);
}

.carousel-nav-left {
  left: 12px;
}

.carousel-nav-right {
  right: 12px;
}

.carousel-nav span {
  font-size: 26px;
  line-height: 1;
}
</style>
