"use client"
import { AnimatePresence, motion } from "motion/react"
import { useMemo, useState } from "react"
import { Button as ButtonRAC } from "react-aria-components"
import { useIntl } from "react-intl"

import { IconButton } from "../../IconButton"
import { Typography } from "../../Typography"

import Image from "../../Image"

import { cx } from "class-variance-authority"
import { useMediaQuery } from "usehooks-ts"
import { LightboxImage } from ".."
import styles from "./gallery.module.css"
import { ImageCounter } from "../../ImageCounter"
import { animationVariants, useKeyboardNavigation } from "../util"
import { ThumbnailImage } from "./ThumnailImage"
import { useThumbnail } from "./useThumbNail"

interface GalleryProps {
  images: LightboxImage[]
  onClose: () => void
  onSelectImage: (image: LightboxImage) => void
  onImageClick: () => void
  selectedImage: LightboxImage | null
  hideLabel?: boolean
}

export function Gallery({
  images,
  onClose,
  onSelectImage,
  onImageClick,
  selectedImage,
  hideLabel,
}: GalleryProps) {
  const intl = useIntl()
  const [slideDirection, setSlideDirection] = useState<"left" | "right">("left")
  const isMobile = useMediaQuery("(max-width: 767px)")

  const mainImage = selectedImage || images[0]
  const mainImageIndex = useMemo(
    () => images.findIndex((img) => img === mainImage),
    [images, mainImage]
  )

  const thumbnail = useThumbnail({
    images: images,
    mainImageIdx: mainImageIndex,
  })

  function handleNext() {
    setSlideDirection("left")
    const nextIndex = (mainImageIndex + 1) % images.length
    onSelectImage(images[nextIndex])
  }
  function handlePrev() {
    setSlideDirection("right")
    const prevIndex = (mainImageIndex - 1 + images.length) % images.length
    onSelectImage(images[prevIndex])
  }
  useKeyboardNavigation(handlePrev, handleNext)

  const hasPrevImage = thumbnail.previous !== undefined
  const hasNextImage = thumbnail.next !== undefined

  return (
    <div className={styles.gallery}>
      <IconButton
        variant="Muted"
        emphasis
        className={styles.closeButton}
        onPress={onClose}
        aria-label={intl.formatMessage({
          id: "common.close",
          defaultMessage: "Close",
        })}
        iconName={isMobile ? "chevron_left" : "close"}
      />

      {/* Desktop Gallery */}
      <div className={styles.desktopGallery}>
        <Typography variant="Body/Supporting text (caption)/smRegular">
          <p className={styles.header}>
            {mainImage.caption && !hideLabel && (
              <span className={styles.caption}>{mainImage.caption}</span>
            )}
          </p>
        </Typography>
        <div className={styles.content}>
          <AnimatePresence initial={false} custom={slideDirection}>
            <motion.div
              key={mainImage.src}
              className={styles.motionContainer}
              custom={slideDirection}
              variants={animationVariants}
              initial="initial"
              animate="animate"
              exit="exit"
              transition={{ duration: 0.3 }}
            >
              <Image
                src={mainImage.src}
                alt={mainImage.alt}
                fill
                sizes="(min-width: 1000px) 1000px, 100vw"
                className={styles.mainImage}
                onClick={onImageClick}
                tabIndex={0}
                aria-label={intl.formatMessage({
                  id: "lightbox.openImage",
                  defaultMessage: "Open image",
                })}
                role="button"
                onKeyDown={(e) => {
                  if (e.key === "Enter" || e.key === " ") {
                    onImageClick()
                  }
                }}
              />
            </motion.div>
          </AnimatePresence>
          <IconButton
            variant="Elevated"
            className={cx(styles.navigationButton, styles.previous)}
            onPress={handlePrev}
            aria-label={intl.formatMessage({
              id: "lightbox.previousImage",
              defaultMessage: "Previous image",
            })}
            iconName="arrow_back"
          />
          <IconButton
            variant="Elevated"
            className={cx(styles.navigationButton, styles.next)}
            onPress={handleNext}
            aria-label={intl.formatMessage({
              id: "lightbox.nextImage",
              defaultMessage: "Next image",
            })}
            iconName="arrow_forward"
          />
          <ImageCounter
            number={`${mainImageIndex + 1} / ${images.length}`}
            className={styles.imageCounter}
          />
        </div>
        <div className={styles.desktopThumbnailGrid}>
          <AnimatePresence initial={false}>
            {hasPrevImage && (
              <ThumbnailImage
                image={thumbnail.previous!}
                key="prev-lightbox-image"
                index={0}
                onSelect={onSelectImage}
              />
            )}
            <span className={styles.thumbnail}>
              {thumbnail.images.map((image, index) => (
                <ThumbnailImage
                  key={image.src}
                  image={image}
                  index={hasPrevImage ? index + 1 : index}
                  onSelect={onSelectImage}
                  isMainImage={mainImage === image}
                />
              ))}
            </span>
            {hasNextImage && (
              <ThumbnailImage
                image={thumbnail.next!}
                key="next-lightbox-image"
                index={6}
                onSelect={onSelectImage}
              />
            )}
          </AnimatePresence>
        </div>
      </div>

      {/* Mobile Gallery */}
      <div className={styles.mobileGallery}>
        {images.map((image, index) => (
          <motion.div
            key={image.src}
            className={cx(styles.thumbnailContainer, {
              [styles.fullWidthImage]: index % 3 === 0,
            })}
            initial={{ opacity: 0, y: 20 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.3, delay: index * 0.05 }}
          >
            <ButtonRAC
              className={styles.imageButton}
              aria-label={intl.formatMessage({
                id: "lightbox.openImage",
                defaultMessage: "Open image",
              })}
              onPress={() => {
                onSelectImage(image)
                onImageClick()
              }}
            >
              <Image
                src={image.src}
                alt={image.alt}
                fill
                sizes="100vw"
                className={styles.image}
              />
            </ButtonRAC>
          </motion.div>
        ))}
      </div>
    </div>
  )
}
