<template>
  <section ref="gallerySectionRef" class="pt-16 pb-28">
    <div class="container mx-auto max-w-5xl px-4">
      <h2
        class="text-2xl sm:text-5xl font-bold tracking-tight text-dark mb-16 text-center"
      >
        <span v-html="t('Photo Gallery')"></span>
      </h2>

      <!-- MOBILE -->
      <div
        class="-mx-4 flex snap-x snap-mandatory gap-4 overflow-x-auto px-4 py-4 md:hidden"
      >
        <button
          v-for="(image, index) in galleryImages"
          :key="`mobile-${index}`"
          ref="mobileItemRefs"
          type="button"
          class="relative shrink-0 snap-center overflow-hidden rounded-2xl"
          @click="openLightbox(index)"
        >
          <img
            :src="image"
            alt="Müco Gallery Image"
            class="aspect-square w-[78vw] max-w-[320px] object-cover"
          />
        </button>
      </div>

      <!-- DESKTOP -->
      <div class="hidden gap-5 md:block md:columns-5">
        <button
          v-for="(image, index) in galleryImages"
          :key="`desktop-${index}`"
          ref="desktopItemRefs"
          type="button"
          class="group relative mb-5 block w-full overflow-hidden rounded-2xl"
          @click="openLightbox(index)"
        >
          <img
            :src="image"
            alt="Müco Gallery Image"
            class="w-full object-cover transition duration-500 group-hover:scale-110"
            :class="imageRatios[index % imageRatios.length]"
          />

          <div
            class="absolute inset-0 bg-black/0 transition group-hover:bg-black/40"
          />

          <div
            class="absolute inset-0 flex items-center justify-center opacity-0 transition group-hover:opacity-100"
          >
            <div class="rounded-full bg-white/90 p-3 text-black">
              <component :is="icons.plus" class="h-4 w-4" />
            </div>
          </div>
        </button>
      </div>
    </div>

    <!-- LIGHTBOX -->
    <div
      v-if="selectedImage"
      class="fixed inset-0 z-50 flex touch-pan-y items-center justify-center bg-black/85 px-4"
      @click.self="closeLightbox"
      @touchstart.passive="onTouchStart"
      @touchmove.passive="onTouchMove"
      @touchend="onTouchEnd"
    >
      <!-- CLOSE -->
      <button
        type="button"
        aria-label="Close"
        class="absolute right-5 top-5 z-20 text-4xl text-white hover:opacity-70"
        @click="closeLightbox"
      >
        ×
      </button>

      <!-- PREV -->
      <button
        type="button"
        aria-label="Previous image"
        class="absolute left-1 top-1/2 z-20 flex h-10 w-10 -translate-y-1/2 items-center justify-center rounded-full bg-white/80 text-2xl text-black hover:bg-white md:left-8 md:h-11 md:w-11"
        @click.stop="prev"
      >
        ‹
      </button>

      <!-- IMAGE -->
      <img
        :key="selectedImage"
        :src="selectedImage"
        alt="Müco Gallery Large Image"
        class="max-h-[90vh] max-w-full select-none rounded-2xl object-contain"
        draggable="false"
      />

      <!-- NEXT -->
      <button
        type="button"
        aria-label="Next image"
        class="absolute right-1 top-1/2 z-20 flex h-10 w-10 -translate-y-1/2 items-center justify-center rounded-full bg-white/80 text-2xl text-black hover:bg-white md:right-8 md:h-11 md:w-11"
        @click.stop="next"
      >
        ›
      </button>
    </div>
  </section>
</template>

<script setup lang="ts">
import { computed, nextTick, onBeforeUnmount, onMounted, ref } from "vue";
import { useI18n } from "vue-i18n";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { useIcons } from "@/composables/useIcons";

gsap.registerPlugin(ScrollTrigger);

const icons = useIcons();
const { t } = useI18n();

const gallerySectionRef = ref<HTMLElement | null>(null);
const mobileItemRefs = ref<HTMLElement[]>([]);
const desktopItemRefs = ref<HTMLElement[]>([]);

let ctx: gsap.Context | null = null;
let mm: gsap.MatchMedia | null = null;

const galleryImages = Array.from(
  { length: 10 },
  (_, i) => `/images/gallery/${i + 1}.jpg`,
);

const imageRatios = ["aspect-square", "aspect-[4/5]", "aspect-[3/4]"];

const selectedIndex = ref<number | null>(null);

const selectedImage = computed(() => {
  if (selectedIndex.value === null) return null;
  return galleryImages[selectedIndex.value];
});

const openLightbox = (index: number) => {
  selectedIndex.value = index;
  document.body.style.overflow = "hidden";
};

const closeLightbox = () => {
  selectedIndex.value = null;
  document.body.style.overflow = "";
};

const next = () => {
  if (selectedIndex.value === null) return;
  selectedIndex.value = (selectedIndex.value + 1) % galleryImages.length;
};

const prev = () => {
  if (selectedIndex.value === null) return;
  selectedIndex.value =
    (selectedIndex.value - 1 + galleryImages.length) % galleryImages.length;
};

const touchStartX = ref(0);
const touchStartY = ref(0);
const touchEndX = ref(0);
const touchEndY = ref(0);

const minSwipeDistance = 50;

const onTouchStart = (event: TouchEvent) => {
  touchStartX.value = event.changedTouches[0].screenX;
  touchStartY.value = event.changedTouches[0].screenY;
  touchEndX.value = event.changedTouches[0].screenX;
  touchEndY.value = event.changedTouches[0].screenY;
};

const onTouchMove = (event: TouchEvent) => {
  touchEndX.value = event.changedTouches[0].screenX;
  touchEndY.value = event.changedTouches[0].screenY;
};

const onTouchEnd = () => {
  const diffX = touchStartX.value - touchEndX.value;
  const diffY = touchStartY.value - touchEndY.value;

  const isHorizontalSwipe = Math.abs(diffX) > Math.abs(diffY);
  const isValidSwipe = Math.abs(diffX) > minSwipeDistance;

  if (!isHorizontalSwipe || !isValidSwipe) return;

  if (diffX > 0) {
    next();
  } else {
    prev();
  }
};

const onKey = (e: KeyboardEvent) => {
  if (selectedIndex.value === null) return;

  if (e.key === "Escape") closeLightbox();
  if (e.key === "ArrowRight") next();
  if (e.key === "ArrowLeft") prev();
};

const animate = (items: HTMLElement[]) => {
  if (!gallerySectionRef.value || !items.length) return;

  gsap.set(items, { scale: 0, opacity: 0 });

  gsap.to(items, {
    scale: 1,
    opacity: 1,
    ease: "back.out(2.2)",
    stagger: { each: 0.08, from: "random" },
    scrollTrigger: {
      trigger: gallerySectionRef.value,
      start: "top 90%",
      end: "top 25%",
      scrub: 1,
    },
  });
};

onMounted(async () => {
  await nextTick();

  ctx = gsap.context(() => {
    mm = gsap.matchMedia();

    mm.add("(min-width: 768px)", () => {
      animate(desktopItemRefs.value);
    });

    mm.add("(max-width: 767px)", () => {
      animate(mobileItemRefs.value);
    });
  }, gallerySectionRef.value ?? undefined);

  window.addEventListener("keydown", onKey);
});

onBeforeUnmount(() => {
  mm?.revert();
  ctx?.revert();
  window.removeEventListener("keydown", onKey);
  document.body.style.overflow = "";
});
</script>
