"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 HotelListingItem from "./HotelListingItem"

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

import type { HotelDataWithUrl } from "@/types/hotel"

interface CampaignHotelListingClientProps {
  heading: string
  hotels: HotelDataWithUrl[]
}

export default function CampaignHotelListingClient({
  heading,
  hotels,
}: CampaignHotelListingClientProps) {
  const intl = useIntl()
  const isMobile = useMediaQuery("(max-width: 767px)")
  const scrollRef = useRef<HTMLElement>(null)

  const initialCount = isMobile ? 3 : 6 // Initial number of hotels to show
  const thresholdCount = isMobile ? 6 : 9 // This is the threshold at which we start showing the "Show More" button
  const showAllThreshold = isMobile ? 9 : 18 // This is the threshold at which we show the "Show All" button
  const incrementCount = isMobile ? 3 : 6 // Number of hotels to increment when the button is clicked

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

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

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

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

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

  if (visibleCount === hotels.length) {
    buttonText = intl.formatMessage({
      defaultMessage: "Show less",
    })
    iconDirection = "keyboard_arrow_up"
  } else if (canShowAll) {
    buttonText = intl.formatMessage({
      defaultMessage: "Show all",
    })
  }

  return (
    <section className={styles.hotelListingSection} ref={scrollRef}>
      <header className={styles.header}>
        <Typography variant="Title/md">
          <h2 className={styles.heading}>{heading}</h2>
        </Typography>
      </header>
      <ul className={styles.list}>
        {hotels.map(({ hotel, url }, index) => (
          <li
            key={hotel.id}
            className={cx(styles.listItem, {
              [styles.hidden]: index >= visibleCount,
            })}
          >
            <HotelListingItem hotel={hotel} url={url} />
          </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>
  )
}
