"use client"

import { usePathname } from "next/navigation"
import { useCallback, useEffect, useRef, useState } from "react"
import { useIntl } from "react-intl"
import { useMediaQuery } from "usehooks-ts"

import { debounce } from "@scandic-hotels/common/utils/debounce"
import { IconButton } from "@scandic-hotels/design-system/IconButton"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { trackClick } from "@scandic-hotels/tracking/base"
import { trpc } from "@scandic-hotels/trpc/client"

import useLang from "@/hooks/useLang"

import { DesktopCampaignBanner } from "./Desktop"
import { MobileCampaignBanner } from "./Mobile"
import { shouldShowCampaignBanner } from "./utils"

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

export default function CampaignBanner() {
  const lang = useLang()
  const intl = useIntl()
  const pathname = usePathname()
  const campaignBannerRef = useRef<HTMLDivElement>(null)
  const isMobile = useMediaQuery("(max-width: 767px)")
  const [closedPaths, setClosedPaths] = useState<Set<string>>(new Set())
  const [
    { data: siteConfig, isLoading: siteConfigLoading },
    { data: campaignBanner, isLoading: campaignBannerLoading },
  ] = trpc.useQueries((t) => [
    t.contentstack.base.siteConfig({ lang }, { refetchInterval: 60_000 }),
    t.contentstack.base.sitewideCampaignBanner.get(
      { lang },
      { refetchInterval: 360_000 }
    ),
  ])
  const isOnSamePage = pathname === campaignBanner?.link?.url
  const sitewideAlertType = siteConfig?.sitewideAlert?.type || null
  const shouldShowBanner = shouldShowCampaignBanner(
    pathname,
    lang,
    closedPaths,
    sitewideAlertType
  )
  const isVisible =
    !siteConfigLoading &&
    !campaignBannerLoading &&
    !!campaignBanner &&
    shouldShowBanner

  const updateHeightRefCallback = useCallback((node: HTMLDivElement | null) => {
    if (node) {
      const debouncedUpdate = debounce(([entry]) => {
        const height = entry.contentRect.height

        document.documentElement.style.setProperty(
          "--campaign-banner-height",
          `${height}px`
        )
      }, 100)

      const observer = new ResizeObserver(debouncedUpdate)
      observer.observe(node)

      return () => {
        if (node) {
          observer.unobserve(node)
        }
        observer.disconnect()
      }
    }
  }, [])

  useEffect(() => {
    if (!isVisible) {
      document.documentElement.style.removeProperty("--campaign-banner-height")
    }
  }, [isVisible])

  if (!isVisible) {
    return null
  }

  function handleClose() {
    trackClick("BW close")
    setClosedPaths((prev) => new Set(prev).add(pathname))
  }

  return (
    <div
      className={styles.campaignBanner}
      ref={(node) => {
        campaignBannerRef.current = node
        return updateHeightRefCallback(node)
      }}
    >
      <div className={styles.content}>
        {isMobile ? (
          <MobileCampaignBanner
            tag={campaignBanner.tag}
            text={campaignBanner.text}
            link={isOnSamePage ? null : campaignBanner.link}
            bookingCode={campaignBanner.booking_code}
          />
        ) : (
          <DesktopCampaignBanner
            tag={campaignBanner.tag}
            text={campaignBanner.text}
            link={isOnSamePage ? null : campaignBanner.link}
            bookingCode={campaignBanner.booking_code}
          />
        )}
        <IconButton
          className={styles.closeButton}
          theme="Inverted"
          style="Muted"
          onPress={handleClose}
          aria-label={intl.formatMessage({
            id: "campaignBanner.dismissBanner",
            defaultMessage: "Dismiss banner",
          })}
        >
          <MaterialIcon color="CurrentColor" icon="close" />
        </IconButton>
      </div>
    </div>
  )
}
