"use client"

import { AnimatePresence, motion } from "framer-motion"
import { usePathname } from "next/navigation"
import React, { useState } from "react"
import { Dialog, Modal, ModalOverlay } from "react-aria-components"
import { useIntl } from "react-intl"

import { customerService } from "@/constants/currentWebHrefs"
import { benefits } from "@/constants/routes/myPages"
import {
  benefits as webviewBenefits,
  myPagesWebviews,
} from "@/constants/routes/webviews"
import { trpc } from "@/lib/trpc/client"

import Link from "@/components/TempDesignSystem/Link"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import { toast } from "@/components/TempDesignSystem/Toasts"
import useLang from "@/hooks/useLang"

import confetti from "./confetti"
import Header from "./Header"
import Initial from "./Initial"
import Navigation from "./Navigation"
import Slide from "./Slide"

import styles from "./surprises.module.css"

import type { SurprisesProps } from "@/types/components/blocks/surprises"
import type { Surprise } from "@/types/components/myPages/rewards"

const MotionModal = motion.create(Modal)

export default function SurprisesNotification({
  surprises: initialData,
}: SurprisesProps) {
  const lang = useLang()
  const intl = useIntl()
  const pathname = usePathname()
  const [open, setOpen] = useState(true)
  const [[selectedSurprise, direction], setSelectedSurprise] = useState([0, 0])
  const [showSurprises, setShowSurprises] = useState(false)
  const utils = trpc.useUtils()

  const { data: surprises } = trpc.contentstack.rewards.surprises.useQuery<
    Surprise[]
  >(
    {
      lang,
    },
    {
      initialData,
      refetchInterval: 1000 * 60 * 5, // every 5 minutes
      refetchIntervalInBackground: false,
    }
  )

  const unwrap = trpc.contentstack.rewards.unwrap.useMutation({
    onSuccess: () => {
      utils.contentstack.rewards.current.invalidate({ lang })

      const onBenefitsPage = pathname.indexOf(benefits[lang]) === 0
      const onWebviewBenefitsPage =
        pathname.indexOf(webviewBenefits[lang]) === 0

      if (onBenefitsPage || onWebviewBenefitsPage) {
        return
      }

      const benefitPageUrl = myPagesWebviews.includes(pathname)
        ? webviewBenefits[lang]
        : benefits[lang]

      toast.success(
        <>
          {intl.formatMessage(
            {
              defaultMessage:
                "{amount, plural, one {Gift} other {Gifts}} added to your benefits",
            },
            { amount: surprises.length }
          )}
          <br />
          <Link href={benefitPageUrl} variant="underscored" color="burgundy">
            {intl.formatMessage({
              defaultMessage: "Go to My Benefits",
            })}
          </Link>
        </>
      )
    },
    onError: (error) => {
      console.error("Failed to unwrap surprise", error)
      toast.error(
        <>
          {intl.formatMessage(
            {
              defaultMessage:
                "Oops! Something went wrong while showing your surprise. Please refresh the page or try again later. If the issue persists, <link>contact the support.</link>",
            },
            {
              link: (str) => (
                <Link textDecoration="underline" href={customerService[lang]}>
                  {str}
                </Link>
              ),
            }
          )}
        </>
      )
    },
  })

  const totalSurprises = surprises.length
  if (!totalSurprises) {
    return null
  }

  const surprise = surprises[selectedSurprise]

  function showSurprise(newDirection: number) {
    setSelectedSurprise(([currentIndex]) => [
      currentIndex + newDirection,
      newDirection,
    ])
  }

  async function viewRewards() {
    const updates = surprises
      .map((surprise) => {
        const coupons = surprise.coupon
          .map((coupon) => {
            if (coupon.couponCode) {
              return {
                rewardId: surprise.id,
                couponCode: coupon.couponCode,
              }
            }
          })
          .filter(
            (coupon): coupon is { rewardId: string; couponCode: string } =>
              !!coupon
          )

        return coupons
      })
      .flat()

    unwrap.mutate(updates)
  }

  return (
    <ModalOverlay
      className={styles.overlay}
      isOpen={open}
      onOpenChange={setOpen}
      isKeyboardDismissDisabled
    >
      <canvas id="surprise-confetti" className={styles.confetti} />
      <AnimatePresence mode="wait">
        {open && (
          <MotionModal
            className={styles.modal}
            initial={{ y: 32, opacity: 0 }}
            animate={{ y: 0, opacity: 1 }}
            exit={{ y: 32, opacity: 0 }}
            transition={{
              y: { duration: 0.4, ease: "easeInOut" },
              opacity: { duration: 0.4, ease: "easeInOut" },
            }}
            onAnimationComplete={confetti}
          >
            <Dialog
              aria-label={intl.formatMessage({
                defaultMessage: "Surprises",
              })}
              className={styles.dialog}
            >
              {({ close }) => {
                return (
                  <>
                    <Header
                      onClose={() => {
                        viewRewards()
                        close()
                      }}
                    >
                      {showSurprises && totalSurprises > 1 && (
                        <Caption type="label" uppercase>
                          {intl.formatMessage(
                            {
                              defaultMessage: "{amount} out of {total}",
                            },
                            {
                              amount: selectedSurprise + 1,
                              total: totalSurprises,
                            }
                          )}
                        </Caption>
                      )}
                    </Header>

                    {showSurprises ? (
                      <>
                        <AnimatePresence
                          mode="popLayout"
                          initial={false}
                          custom={direction}
                        >
                          <motion.div
                            key={selectedSurprise}
                            custom={direction}
                            variants={variants}
                            initial="enter"
                            animate="center"
                            exit="exit"
                            transition={{
                              x: { type: "ease", duration: 0.5 },
                              opacity: { duration: 0.2 },
                            }}
                            layout
                          >
                            <Slide surprise={surprise} />
                          </motion.div>
                        </AnimatePresence>

                        {totalSurprises > 1 && (
                          <Navigation
                            selectedSurprise={selectedSurprise}
                            totalSurprises={totalSurprises}
                            showSurprise={showSurprise}
                          />
                        )}
                      </>
                    ) : (
                      <Initial
                        totalSurprises={totalSurprises}
                        onOpen={() => {
                          setShowSurprises(true)
                        }}
                      />
                    )}
                  </>
                )
              }}
            </Dialog>
          </MotionModal>
        )}
      </AnimatePresence>
    </ModalOverlay>
  )
}

const variants = {
  enter: (direction: number) => {
    return {
      x: direction > 0 ? 1000 : -1000,
      opacity: 0,
    }
  },
  center: {
    x: 0,
    opacity: 1,
  },
  exit: (direction: number) => {
    return {
      x: direction < 0 ? 1000 : -1000,
      opacity: 0,
    }
  },
}
