<script setup lang="ts">
import type { PoiImageAsset } from '@/domain/poi'
import { computed, ref, watch } from 'vue'
import PoiImage from './PoiImage.vue'

interface Props {
  images: ReadonlyArray<PoiImageAsset>
  name: string
  initialIndex?: number
  height?: string | number
  fallbackSrc?: string
  showIndicator?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  initialIndex: 0,
  height: '422rpx',
  fallbackSrc: '/static/poi/placeholder.png',
  showIndicator: true,
})

const emit = defineEmits<{
  change: [index: number]
  imageError: [image: PoiImageAsset, index: number, event: unknown]
}>()

const currentIndex = ref(0)
const galleryHeight = computed(() => (
  typeof props.height === 'number' ? `${props.height}rpx` : props.height
))
const hasImages = computed(() => props.images.length > 0)

function clampIndex(index: number): number {
  if (!hasImages.value)
    return 0

  return Math.min(Math.max(0, Math.floor(index)), props.images.length - 1)
}

function handleChange(event: { detail: { current: number } }): void {
  currentIndex.value = clampIndex(Number(event.detail.current))
  emit('change', currentIndex.value)
}

function handleImageError(image: PoiImageAsset, index: number, event: unknown): void {
  emit('imageError', image, index, event)
}

watch(
  () => [props.initialIndex, props.images.length],
  () => {
    currentIndex.value = clampIndex(props.initialIndex)
  },
  { immediate: true },
)
</script>

<template>
  <view class="poi-hero-gallery" :style="{ height: galleryHeight }">
    <swiper
      v-if="hasImages"
      class="poi-hero-gallery__swiper"
      :current="currentIndex"
      :circular="images.length > 1"
      :duration="300"
      @change="handleChange"
    >
      <swiper-item v-for="(image, index) in images" :key="image.id">
        <PoiImage
          :src="image.url"
          :alt="image.alt || `${name}图片${index + 1}`"
          :fallback-src="fallbackSrc"
          width="100%"
          height="100%"
          @error="handleImageError(image, index, $event)"
        />
      </swiper-item>
    </swiper>

    <PoiImage
      v-else
      src=""
      :alt="`${name}图片暂不可用`"
      :fallback-src="fallbackSrc"
      width="100%"
      height="100%"
    />

    <view
      v-if="showIndicator && images.length > 1"
      class="poi-hero-gallery__indicator"
      aria-live="polite"
    >
      {{ currentIndex + 1 }} / {{ images.length }}
    </view>
  </view>
</template>

<style scoped lang="scss">
.poi-hero-gallery {
  position: relative;
  width: 100%;
  overflow: hidden;
  background: #e8eeeb;
}

.poi-hero-gallery__swiper {
  width: 100%;
  height: 100%;
}

.poi-hero-gallery__indicator {
  position: absolute;
  right: 28rpx;
  bottom: 24rpx;
  box-sizing: border-box;
  min-width: 80rpx;
  padding: 8rpx 18rpx;
  font-size: 22rpx;
  font-weight: 600;
  line-height: 32rpx;
  color: #fff;
  text-align: center;
  background: rgb(0 0 0 / 58%);
  border-radius: 24rpx;
}
</style>
