<template>
  <div :class="['safe-image', wrapperClass, { 'is-clickable': clickable }]" @click="handleClick">
    <div v-if="!loaded" class="safe-image__placeholder">
      <div class="safe-image__shimmer"></div>
    </div>
    <img
        :alt="alt"
        :class="['safe-image__img', imgClass, { 'is-loaded': loaded }]"
        :loading="lazy ? 'lazy' : 'eager'"
        :src="currentSrc"
        @error="handleError"
        @load="handleLoad"
    >
  </div>
</template>

<script lang="ts" setup>
import {ref, watch} from 'vue'
import {DEFAULT_PRODUCT_IMAGE, resolveImageUrl} from '@/utils/image'

interface Props {
  src?: string | null
  alt?: string
  imgClass?: string
  wrapperClass?: string
  lazy?: boolean
  clickable?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  alt: '',
  imgClass: '',
  wrapperClass: '',
  lazy: true,
  clickable: false,
})

const emit = defineEmits<{
  click: []
}>()

const currentSrc = ref(DEFAULT_PRODUCT_IMAGE)
const loaded = ref(false)
const fallbackApplied = ref(false)

const resetSource = () => {
  currentSrc.value = resolveImageUrl(props.src)
  loaded.value = false
  fallbackApplied.value = false
}

watch(() => props.src, resetSource, {immediate: true})

const handleLoad = () => {
  loaded.value = true
}

const handleError = () => {
  if (fallbackApplied.value) {
    loaded.value = true
    return
  }

  fallbackApplied.value = true
  currentSrc.value = DEFAULT_PRODUCT_IMAGE
}

const handleClick = () => {
  if (props.clickable) {
    emit('click')
  }
}
</script>

<style lang="scss" scoped>
.safe-image {
  position: relative;
  overflow: hidden;
  background: #f4ede4;

  &.is-clickable {
    cursor: pointer;
  }

  &__placeholder {
    position: absolute;
    inset: 0;
    background: #f4ede4;
  }

  &__shimmer {
    width: 100%;
    height: 100%;
    background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(0, 0, 0, 0.06) 50%, rgba(255, 255, 255, 0) 100%);
    animation: shimmer 1.4s infinite;
  }

  &__img {
    width: 100%;
    height: 100%;
    opacity: 0;
    transition: opacity 0.2s ease;
    display: block;

    &.is-loaded {
      opacity: 1;
    }
  }
}

@keyframes shimmer {
  0% {
    transform: translateX(-100%);
  }
  100% {
    transform: translateX(100%);
  }
}
</style>
