"use client"

import { motion } from "framer-motion"
import { type PropsWithChildren, useEffect, useState } from "react"
import {
  Dialog,
  DialogTrigger,
  Modal as AriaModal,
  ModalOverlay,
} from "react-aria-components"
import { useIntl } from "react-intl"

import { CloseLargeIcon } from "@/components/Icons"
import Preamble from "@/components/TempDesignSystem/Text/Preamble"
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"

import {
  type AnimationState,
  AnimationStateEnum,
  type InnerModalProps,
  type ModalProps,
} from "./modal"
import { fade, slideInOut } from "./motionVariants"

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

const MotionOverlay = motion(ModalOverlay)
const MotionModal = motion(AriaModal)

function InnerModal({
  animation,
  onAnimationComplete = () => undefined,
  setAnimation,
  onToggle,
  isOpen,
  children,
  title,
  subtitle,
}: PropsWithChildren<InnerModalProps>) {
  const intl = useIntl()
  function modalStateHandler(newAnimationState: AnimationState) {
    setAnimation((currentAnimationState) =>
      newAnimationState === AnimationStateEnum.hidden &&
      currentAnimationState === AnimationStateEnum.hidden
        ? AnimationStateEnum.unmounted
        : currentAnimationState
    )
    if (newAnimationState === AnimationStateEnum.visible) {
      onAnimationComplete()
    }
  }

  function onOpenChange(state: boolean) {
    onToggle!(state)
  }

  return (
    <MotionOverlay
      animate={animation}
      className={styles.overlay}
      initial={"hidden"}
      isDismissable
      isExiting={animation === AnimationStateEnum.hidden}
      onAnimationComplete={modalStateHandler}
      variants={fade}
      isOpen={isOpen}
      onOpenChange={onOpenChange}
    >
      <MotionModal
        className={styles.modal}
        variants={slideInOut}
        animate={animation}
        initial={"hidden"}
      >
        <Dialog className={styles.dialog} aria-label="Dialog">
          {({ close }) => (
            <>
              <header className={styles.header}>
                <div>
                  {title && (
                    <Subtitle type="one" color="uiTextHighContrast">
                      {title}
                    </Subtitle>
                  )}
                  {subtitle && (
                    <Preamble asChild>
                      <span>{subtitle}</span>
                    </Preamble>
                  )}
                </div>

                <button onClick={close} type="button" className={styles.close}>
                  <CloseLargeIcon color="uiTextMediumContrast" />
                </button>
              </header>
              <section className={styles.content}>{children}</section>
            </>
          )}
        </Dialog>
      </MotionModal>
    </MotionOverlay>
  )
}

export default function Modal({
  onAnimationComplete = () => undefined,
  trigger,
  isOpen,
  onToggle,
  title,
  subtitle,
  children,
}: PropsWithChildren<ModalProps>) {
  const [animation, setAnimation] = useState<AnimationState>(
    AnimationStateEnum.visible
  )

  useEffect(() => {
    if (typeof isOpen === "boolean") {
      setAnimation(
        isOpen ? AnimationStateEnum.visible : AnimationStateEnum.hidden
      )
    }
    if (isOpen === undefined) {
      setAnimation(AnimationStateEnum.unmounted)
    }
  }, [isOpen])

  if (!trigger) {
    return (
      <InnerModal
        onAnimationComplete={onAnimationComplete}
        animation={animation}
        setAnimation={setAnimation}
        onToggle={onToggle}
        isOpen={isOpen}
        title={title}
        subtitle={subtitle}
      >
        {children}
      </InnerModal>
    )
  }

  return (
    <DialogTrigger
      onOpenChange={(isOpen) =>
        setAnimation(
          isOpen ? AnimationStateEnum.visible : AnimationStateEnum.hidden
        )
      }
    >
      {trigger}
      <InnerModal
        onAnimationComplete={onAnimationComplete}
        animation={animation}
        setAnimation={setAnimation}
        title={title}
        subtitle={subtitle}
      >
        {children}
      </InnerModal>
    </DialogTrigger>
  )
}
