"use client"

import { useCallback, useEffect, useState } from "react"
import {
  Button,
  Dialog,
  DialogTrigger,
  Modal,
  Popover,
} from "react-aria-components"
import { useFormContext } from "react-hook-form"
import { useIntl } from "react-intl"
import { useMediaQuery } from "usehooks-ts"

import Body from "@/components/TempDesignSystem/Text/Body"

import PickerForm from "./Form"

import styles from "./guests-rooms-picker.module.css"

import type { TGuestsRoom } from "@/types/components/bookingWidget/guestsRoomsPicker"

export default function GuestsRoomsPickerForm() {
  const { watch, trigger } = useFormContext()
  const rooms = watch("rooms") as TGuestsRoom[]

  const checkIsDesktop = useMediaQuery("(min-width: 1367px)")
  const [isDesktop, setIsDesktop] = useState(true)
  const [isOpen, setIsOpen] = useState(false)
  const [containerHeight, setContainerHeight] = useState(0)
  const childCount = rooms[0] ? rooms[0].child.length : 0 // ToDo Update for multiroom later

  const htmlElement =
    typeof window !== "undefined" ? document.querySelector("body") : null
  //isOpen is the 'old state', so isOpen === true means "The modal is open and WILL be closed".
  async function setOverflowClip(isOpen: boolean) {
    if (htmlElement) {
      if (isOpen) {
        htmlElement.style.overflow = "visible"
      } else {
        // !important needed to override 'overflow: hidden' set by react-aria.
        // 'overflow: hidden' does not work in combination with other sticky positioned elements, which clip does.
        htmlElement.style.overflow = "clip !important"
      }
    }
    if (!isOpen) {
      const state = await trigger("rooms")
      if (state) {
        setIsOpen(isOpen)
      }
    }
  }

  useEffect(() => {
    setIsDesktop(checkIsDesktop)
  }, [checkIsDesktop])

  const updateHeight = useCallback(() => {
    if (typeof window !== undefined) {
      // Get available space for picker to show without going beyond screen
      let maxHeight =
        window.innerHeight -
        (document.querySelector("#booking-widget")?.getBoundingClientRect()
          .bottom ?? 0) -
        50
      const innerContainerHeight = document
        .querySelector(".guests_picker_popover")
        ?.getBoundingClientRect().height
      if (
        maxHeight != containerHeight &&
        innerContainerHeight &&
        maxHeight <= innerContainerHeight
      ) {
        setContainerHeight(maxHeight)
      } else if (
        containerHeight &&
        innerContainerHeight &&
        maxHeight > innerContainerHeight
      ) {
        setContainerHeight(0)
      }
    }
  }, [containerHeight])

  useEffect(() => {
    if (typeof window !== undefined && isDesktop && rooms.length > 0) {
      updateHeight()
    }
  }, [childCount, isDesktop, updateHeight, rooms])

  return isDesktop ? (
    <DialogTrigger onOpenChange={setOverflowClip} isOpen={isOpen}>
      <Trigger
        rooms={rooms}
        className={styles.triggerDesktop}
        triggerFn={() => {
          setIsOpen(true)
        }}
      />
      <Popover
        className="guests_picker_popover"
        placement="bottom start"
        offset={36}
        style={containerHeight ? { overflow: "auto" } : {}}
      >
        <Dialog className={styles.pickerContainerDesktop}>
          {({ close }) => <PickerForm rooms={rooms} onClose={close} />}
        </Dialog>
      </Popover>
    </DialogTrigger>
  ) : (
    <DialogTrigger onOpenChange={setOverflowClip} isOpen={isOpen}>
      <Trigger
        rooms={rooms}
        className={styles.triggerMobile}
        triggerFn={() => {
          setIsOpen(true)
        }}
      />
      <Modal>
        <Dialog className={styles.pickerContainerMobile}>
          {({ close }) => <PickerForm rooms={rooms} onClose={close} />}
        </Dialog>
      </Modal>
    </DialogTrigger>
  )
}

function Trigger({
  rooms,
  className,
  triggerFn,
}: {
  rooms: TGuestsRoom[]
  className: string
  triggerFn?: () => void
}) {
  const intl = useIntl()

  return (
    <Button
      className={`${className} ${styles.btn}`}
      type="button"
      onPress={triggerFn}
    >
      <Body color="uiTextHighContrast">
        <span>
          {intl.formatMessage(
            { id: "booking.rooms" },
            { totalRooms: rooms.length }
          )}
          {", "}
          {intl.formatMessage(
            { id: "booking.adults" },
            { totalAdults: rooms.reduce((acc, room) => acc + room.adults, 0) }
          )}
          {rooms.some((room) => room.child.length > 0)
            ? ", " +
              intl.formatMessage(
                { id: "booking.children" },
                {
                  totalChildren: rooms.reduce(
                    (acc, room) => acc + room.child.length,
                    0
                  ),
                }
              )
            : null}
        </span>
      </Body>
    </Button>
  )
}
