"use client"

import { cx } from "class-variance-authority"
import { useRef, useState } from "react"
import { useIntl } from "react-intl"
import { useMediaQuery } from "usehooks-ts"

import { Button } from "@scandic-hotels/design-system/Button"
import {
  MaterialIcon,
  type MaterialIconProps,
} from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"

import { useHotelListingDataStore } from "@/stores/hotel-listing-data"

import CampaignHotelListingSkeleton from "@/components/Blocks/CampaignHotelListing/CampaignHotelListingSkeleton"
import HotelFilterAndSort from "@/components/HotelFilterAndSort"

import HotelListingItem from "./HotelListingItem"

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

interface CampaignHotelListingClientProps {
  heading: string
  preamble?: string | null
  bookingCode?: string | null
  visibleCountMobile: 3 | 6
  visibleCountDesktop: 3 | 6
  isMainBlock: boolean
}

export default function CampaignHotelListingClient({
  heading,
  preamble,
  visibleCountMobile,
  visibleCountDesktop,
  isMainBlock,
  bookingCode,
}: CampaignHotelListingClientProps) {
  const intl = useIntl()
  const isMobile = useMediaQuery("(max-width: 767px)")
  const scrollRef = useRef<HTMLElement>(null)
  const { activeHotels, isLoading } = useHotelListingDataStore((state) => ({
    activeHotels: state.activeHotels,
    isLoading: state.isLoading,
  }))

  const initialCount = isMobile ? visibleCountMobile : visibleCountDesktop // Initial number of activeHotels to show
  const thresholdCount = initialCount + 3 // This is the threshold at which we start showing the "Show More" button
  const showAllThreshold = initialCount * 3 // This is the threshold at which we show the "Show All" button
  const incrementCount = initialCount // Number of activeHotels to increment when the button is clicked

  const [visibleCount, setVisibleCount] = useState(() =>
    // Set initial visible count based on the number of activeHotels and the threshold
    activeHotels.length <= thresholdCount ? activeHotels.length : initialCount
  )

  // Only show the show more/less button if the length of activeHotels exceeds the threshold count
  const showButton = activeHotels.length > thresholdCount

  // Determine if we are at the stage where the user can click to show all activeHotels
  const canShowAll =
    activeHotels.length > visibleCount &&
    (visibleCount + incrementCount > showAllThreshold ||
      visibleCount + incrementCount >= activeHotels.length)

  function handleButtonClick() {
    if (visibleCount < activeHotels.length) {
      if (canShowAll) {
        setVisibleCount(activeHotels.length)
      } else {
        setVisibleCount((prev) =>
          Math.min(prev + incrementCount, activeHotels.length)
        )
      }
    } else {
      setVisibleCount(initialCount)
      if (scrollRef.current) {
        scrollRef.current.scrollIntoView({ behavior: "smooth" })
      }
    }
  }

  let buttonText = intl.formatMessage({
    id: "common.showMore",
    defaultMessage: "Show more",
  })
  let iconDirection: MaterialIconProps["icon"] = "keyboard_arrow_down"

  if (visibleCount === activeHotels.length) {
    buttonText = intl.formatMessage({
      id: "common.showLess",
      defaultMessage: "Show less",
    })
    iconDirection = "keyboard_arrow_up"
  } else if (canShowAll) {
    buttonText = intl.formatMessage({
      id: "common.showAll",
      defaultMessage: "Show all",
    })
  }

  if (isLoading) {
    return <CampaignHotelListingSkeleton />
  }

  return (
    <section
      className={cx(styles.hotelListingSection, {
        [styles.isMainBlock]: isMainBlock,
      })}
      ref={scrollRef}
    >
      <header className={styles.header}>
        <Typography variant={isMainBlock ? "Title/md" : "Title/Subtitle/lg"}>
          <h3 className={styles.heading}>{heading}</h3>
        </Typography>
        {isMainBlock ? <HotelFilterAndSort /> : null}
        {preamble ? (
          <Typography variant="Body/Paragraph/mdRegular">
            <p className={styles.preamble}>{preamble}</p>
          </Typography>
        ) : null}
      </header>
      <ul className={styles.list}>
        {activeHotels.map(({ hotel, url }, index) => {
          const urlWithOptionalBookingCode = bookingCode
            ? `${url}?bookingCode=${bookingCode}`
            : url
          return (
            <li
              key={hotel.id}
              className={cx(styles.listItem, {
                [styles.hidden]: index >= visibleCount,
              })}
            >
              <HotelListingItem
                hotel={hotel}
                url={urlWithOptionalBookingCode}
              />
            </li>
          )
        })}
      </ul>

      {showButton ? (
        <Button
          variant="Text"
          color="Primary"
          size="Medium"
          typography="Body/Paragraph/mdBold"
          onPress={handleButtonClick}
        >
          <MaterialIcon icon={iconDirection} color="CurrentColor" />
          {buttonText}
        </Button>
      ) : null}
    </section>
  )
}
