<template>
  <div class="lazy-receipt-image" ref="containerRef">
    <!-- Loading state -->
    <div v-if="!loaded && !error" class="loading-state">
      <span class="loading loading-spinner loading-sm"></span>
      <span class="text-xs text-gray-500">Loading...</span>
    </div>

    <!-- Error state -->
    <div v-else-if="error" class="error-state" @click="retry">
      <Icon name="mdi:image-broken" class="w-8 h-8 text-red-400" />
      <span class="text-xs text-red-500">Failed to load</span>
      <span class="text-xs text-gray-500">Click to retry</span>
    </div>

    <!-- Loaded image -->
    <img
      v-else-if="loaded && imageUrl"
      :src="imageUrl"
      :alt="alt"
      :class="['receipt-img', imageClass]"
      @error="handleImageError"
      @load="handleImageLoad"
    />

    <!-- Fallback if no URL -->
    <div v-else class="no-image-state">
      <Icon name="mdi:receipt-outline" class="w-8 h-8 text-gray-400" />
      <span class="text-xs text-gray-500">No image</span>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from 'vue';
import type { ExpenseReceipt } from '@/utils/types';

// Props
interface Props {
  receipt: ExpenseReceipt;
  alt?: string;
  useCardCover?: boolean;
  useSmall?: boolean;
  useTiny?: boolean;
  imageClass?: string;
}

const props = withDefaults(defineProps<Props>(), {
  alt: 'Receipt image',
  useCardCover: true,
  useSmall: false,
  useTiny: false,
  imageClass: ''
});

// Reactive state
const containerRef = ref<HTMLElement>();
const loaded = ref(false);
const error = ref(false);
const isVisible = ref(false);

// Computed
const imageUrl = computed(() => {
  if (!props.receipt) return null;
  
  // Choose the appropriate image size based on props
  if (props.useTiny && props.receipt.thumbnails?.tiny?.signedUrl) {
    return props.receipt.thumbnails.tiny.signedUrl;
  }
  
  if (props.useSmall && props.receipt.thumbnails?.small?.signedUrl) {
    return props.receipt.thumbnails.small.signedUrl;
  }
  
  if (props.useCardCover && props.receipt.thumbnails?.card_cover?.signedUrl) {
    return props.receipt.thumbnails.card_cover.signedUrl;
  }
  
  // Fallback to full-size image
  return props.receipt.signedUrl || props.receipt.url;
});

// Intersection Observer for lazy loading
let observer: IntersectionObserver | null = null;

const initIntersectionObserver = () => {
  if (!containerRef.value || typeof IntersectionObserver === 'undefined') {
    // Fallback for environments without IntersectionObserver
    isVisible.value = true;
    loadImage();
    return;
  }

  observer = new IntersectionObserver(
    (entries) => {
      const entry = entries[0];
      if (entry.isIntersecting && !isVisible.value) {
        isVisible.value = true;
        loadImage();
        
        // Stop observing once visible
        if (observer && containerRef.value) {
          observer.unobserve(containerRef.value);
        }
      }
    },
    {
      rootMargin: '50px', // Start loading 50px before the image comes into view
      threshold: 0.1
    }
  );

  observer.observe(containerRef.value);
};

const loadImage = () => {
  if (!imageUrl.value || loaded.value) return;
  
  console.log('[LazyReceiptImage] Loading image:', imageUrl.value);
  
  // Pre-load the image to handle errors properly
  const img = new Image();
  
  img.onload = () => {
    console.log('[LazyReceiptImage] Image loaded successfully');
    loaded.value = true;
    error.value = false;
  };
  
  img.onerror = () => {
    console.error('[LazyReceiptImage] Failed to load image:', imageUrl.value);
    error.value = true;
    loaded.value = false;
  };
  
  img.src = imageUrl.value;
};

const handleImageLoad = () => {
  console.log('[LazyReceiptImage] Image displayed successfully');
};

const handleImageError = () => {
  console.error('[LazyReceiptImage] Image display error:', imageUrl.value);
  error.value = true;
  loaded.value = false;
};

const retry = () => {
  console.log('[LazyReceiptImage] Retrying image load');
  error.value = false;
  loaded.value = false;
  loadImage();
};

// Lifecycle
onMounted(() => {
  initIntersectionObserver();
});

onUnmounted(() => {
  if (observer && containerRef.value) {
    observer.unobserve(containerRef.value);
    observer = null;
  }
});
</script>

<style scoped>
.lazy-receipt-image {
  @apply relative w-full h-full flex items-center justify-center bg-gray-50 dark:bg-gray-700;
}

.loading-state {
  @apply flex flex-col items-center justify-center gap-2 text-gray-500;
}

.error-state {
  @apply flex flex-col items-center justify-center gap-1 text-red-500 cursor-pointer hover:bg-red-50 dark:hover:bg-red-950 transition-colors rounded p-2;
}

.no-image-state {
  @apply flex flex-col items-center justify-center gap-1 text-gray-400;
}

.receipt-img {
  @apply w-full h-full object-cover transition-opacity duration-300;
}

.receipt-img:hover {
  @apply opacity-90;
}
</style>
