<script lang="ts" setup>
import type { ProjectContent } from "~/types/singleProject";

const props = defineProps<{
  projectContent:
    | ProjectContent["videos"]
    | ComputedRef<ProjectContent["videos"]>;
}>();
const videos = computed(() =>
  Array.isArray(props.projectContent)
    ? props.projectContent
    : props.projectContent.value,
);

const currentIndex = ref(0);
const videoRefs = ref<(HTMLVideoElement | null)[]>([]);
const playingVideoIndex = ref<number | null>(null);
const youtubeEmbedUrls = ref<Map<number, string>>(new Map());
const direction = ref<"left" | "right">("left");

const YOUTUBE_REGEX =
  /(?:youtube\.com\/(?:.*v=|embed\/|shorts\/)|youtu\.be\/)([a-zA-Z0-9_-]{11})/;

const isYouTubeVideo = (url: string): boolean =>
  url.includes("youtube") || url.includes("youtu.be");

const getYouTubeVideoId = (url: string): string | null => {
  const match = url.match(YOUTUBE_REGEX);
  return match ? match[1] : null;
};

const getYouTubeThumbnail = (url: string): string => {
  const videoId = getYouTubeVideoId(url);
  return videoId
    ? `https://img.youtube.com/vi/${videoId}/maxresdefault.jpg`
    : "";
};

const getYouTubeEmbedUrl = (url: string, autoplay = false): string => {
  const videoId = getYouTubeVideoId(url);
  if (!videoId) return "";

  const params = new URLSearchParams({
    mute: "1",
    ...(autoplay && { autoplay: "1" }),
  });

  return `https://www.youtube.com/embed/${videoId}?${params.toString()}`;
};

const goToPrevious = () => {
  if (videos.value.length === 0) return;
  direction.value = "right";
  currentIndex.value =
    (currentIndex.value - 1 + videos.value.length) % videos.value.length;
};

const goToNext = () => {
  if (videos.value.length === 0) return;
  direction.value = "left";
  currentIndex.value = (currentIndex.value + 1) % videos.value.length;
};

const goToSlide = (index: number) => {
  if (index >= 0 && index < videos.value.length) {
    direction.value = index > currentIndex.value ? "left" : "right";
    currentIndex.value = index;
  }
};

const setVideoRef = (
  el: Element | ComponentPublicInstance | null,
  index: number,
) => {
  while (videoRefs.value.length <= index) videoRefs.value.push(null);
  videoRefs.value[index] = el instanceof HTMLVideoElement ? el : null;
};

// Play logic
const playVideo = (index: number) => {
  const project = videos.value[index];
  if (!project) return;

  playingVideoIndex.value = index;

  try {
    if (isYouTubeVideo(project.video_url)) {
      youtubeEmbedUrls.value.set(
        index,
        getYouTubeEmbedUrl(project.video_url, true),
      );
    } else {
      const video = videoRefs.value[index];
      video?.play().catch(() => {
        playingVideoIndex.value = null;
      });
    }
  } catch {
    playingVideoIndex.value = null;
  }
};

watch(currentIndex, () => {
  playingVideoIndex.value = null;
});
</script>

<template>
  <div class="relative w-full">
    <div class="relative aspect-video w-full overflow-hidden rounded-2xl">
      <Transition :name="`slide-${direction}`" mode="out-in">
        <div
          v-if="videos[currentIndex]"
          :key="currentIndex"
          class="h-full w-full"
        >
          <!-- YouTube -->
          <template v-if="isYouTubeVideo(videos[currentIndex].video_url)">
            <template v-if="playingVideoIndex !== currentIndex">
              <NuxtImg
                :src="getYouTubeThumbnail(videos[currentIndex].video_url)"
                class="gallery-media"
                :alt="videos[currentIndex]?.alt_image || 'Youtube thumbnail'"
              />
            </template>
            <template v-else>
              <iframe
                class="gallery-media aspect-video"
                :src="youtubeEmbedUrls.get(currentIndex) || ''"
                frameborder="0"
                allowfullscreen
                allow="autoplay; encrypted-media"
              />
            </template>
          </template>

          <!-- MP4 -->
          <template v-else>
            <video
              :ref="(el) => setVideoRef(el, currentIndex)"
              :src="videos[currentIndex].video_url"
              class="gallery-media aspect-video"
              controls
              muted
              loop
            />
          </template>

          <!-- Overlay -->
          <div
            v-if="playingVideoIndex !== currentIndex"
            class="absolute inset-0 flex cursor-pointer items-center justify-center rounded-2xl bg-[rgba(0,0,0,0.5)]"
            @click="playVideo(currentIndex)"
          >
            <SvgVideoButton class="h-[40px] w-[40px]" />
          </div>
        </div>
      </Transition>
    </div>

    <!-- Controls -->
    <div
      v-if="videos.length > 1"
      class="relative z-10 mt-6 flex items-center justify-center gap-6"
    >
      <button
        class="bg-surface-background border-surface-border flex-shrink-0 cursor-pointer rounded border p-3"
        :disabled="videos.length === 0"
        aria-label="Previous video"
        @click="goToPrevious"
      >
        <SvgGradientFullArrowLeft class="rtl:scale-x-[-1]" />
      </button>

      <!-- Pagination -->
      <div class="flex flex-wrap items-center justify-center gap-2">
        <div
          v-for="(video, index) in videos"
          :key="`pagination-${index}`"
          class="pagination-dot"
          :class="{ active: currentIndex === index }"
          @click="goToSlide(index)"
        />
      </div>

      <button
        class="bg-surface-background border-surface-border flex-shrink-0 cursor-pointer rounded border p-3"
        :disabled="videos.length === 0"
        aria-label="Next video"
        @click="goToNext"
      >
        <SvgGradientFullArrowRight class="rtl:scale-x-[-1]" />
      </button>
    </div>
  </div>
</template>

<style scoped>
.gallery-media {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 16px;
  background-color: var(--surface-background);
}

.pagination-dot {
  width: 28px;
  height: 6px;
  border-radius: 2px;
  background-color: var(--surface-background);
  border: 1px solid var(--surface-border);
  cursor: pointer;
  transition: all 0.3s ease;
}
.pagination-dot:hover {
  transform: scale(1.1);
}
.pagination-dot.active {
  background-color: var(--foreground);
}

.dark .pagination-dot {
  background-color: rgba(75, 85, 99, 0.5);
}
.dark .pagination-dot.active {
  background-color: var(--foreground);
}

/* Slide left */
.slide-left-enter-active,
.slide-left-leave-active {
  transition: all 400ms cubic-bezier(0.4, 0, 0.2, 1);
  position: absolute;
  width: 100%;
  height: 100%;
}
.slide-left-enter-from {
  transform: translateX(100%);
  opacity: 0;
}
.slide-left-enter-to {
  transform: translateX(0);
  opacity: 1;
}
.slide-left-leave-from {
  transform: translateX(0);
  opacity: 1;
}
.slide-left-leave-to {
  transform: translateX(-100%);
  opacity: 0;
}

/* Slide right */
.slide-right-enter-active,
.slide-right-leave-active {
  transition: all 400ms cubic-bezier(0.4, 0, 0.2, 1);
  position: absolute;
  width: 100%;
  height: 100%;
}
.slide-right-enter-from {
  transform: translateX(-100%);
  opacity: 0;
}
.slide-right-enter-to {
  transform: translateX(0);
  opacity: 1;
}
.slide-right-leave-from {
  transform: translateX(0);
  opacity: 1;
}
.slide-right-leave-to {
  transform: translateX(100%);
  opacity: 0;
}
</style>
