"use client"

import { cx } from "class-variance-authority"
import {
  type ReadonlyURLSearchParams,
  useParams,
  useRouter,
  useSearchParams,
} from "next/navigation"
import { memo } from "react"
import { useIntl } from "react-intl"

import TripAdvisorChip from "@scandic-hotels/booking-flow/components/TripAdvisorChip"
import {
  alternativeHotelsMap,
  selectHotelMap,
  selectRate,
} from "@scandic-hotels/common/constants/routes/hotelReservation"
import Caption from "@scandic-hotels/design-system/Caption"
import { Divider } from "@scandic-hotels/design-system/Divider"
import HotelLogoIcon from "@scandic-hotels/design-system/Icons/HotelLogoIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"

import { useHotelsMapStore } from "@/stores/hotels-map"

import BookingCodeChip from "@/components/BookingCodeChip"
import { FacilityToIcon } from "@/components/ContentType/HotelPage/data"
import ImageGallery from "@/components/ImageGallery"
import Link from "@/components/TempDesignSystem/Link"
import { mapApiImagesToGalleryImages } from "@/utils/imageGallery"
import { getSingleDecimal } from "@/utils/numberFormatting"

import ReadMore from "../ReadMore"
import HotelChequeCard from "./HotelChequeCard"
import HotelPointsRow from "./HotelPointsRow"
import HotelPriceCard from "./HotelPriceCard"
import HotelVoucherCard from "./HotelVoucherCard"
import NoPriceAvailableCard from "./NoPriceAvailableCard"
import { hotelCardVariants } from "./variants"

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

import type { Lang } from "@scandic-hotels/common/constants/language"

import { HotelCardListingTypeEnum } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
import type { HotelCardProps } from "@/types/components/hotelReservation/selectHotel/hotelCardProps"
import { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek"

function HotelCard({
  hotelData: { availability, hotel },
  isUserLoggedIn,
  state = "default",
  type = HotelCardListingTypeEnum.PageListing,
  bookingCode = "",
  isAlternative,
}: HotelCardProps) {
  const params = useParams()
  const searchParams = useSearchParams()

  const lang = params.lang as Lang
  const intl = useIntl()
  const { activate, engage, disengage, disengageAfterDelay } =
    useHotelsMapStore()

  const amenities = hotel.detailedFacilities.slice(0, 5)
  const router = useRouter()
  const classNames = hotelCardVariants({
    type,
    state,
  })

  const mapUrl = isAlternative
    ? alternativeHotelsMap(lang)
    : selectHotelMap(lang)
  const handleAddressClick = (event: React.MouseEvent) => {
    event.preventDefault()
    disengage() // Disengage the current hotel to avoid the hover state from being active when clicking on the address
    activate(hotel.name)
    router.push(`${mapUrl}?${searchParams.toString()}`)
  }

  const addressStr = `${hotel.address.streetAddress}, ${hotel.address.city}`
  const galleryImages = mapApiImagesToGalleryImages(hotel.galleryImages || [])
  const fullPrice = !availability.bookingCode
  const price = availability.productType

  const hasInsufficientPoints = !price?.redemptions?.some(
    (r) => r.hasEnoughPoints
  )
  const notEnoughPointsLabel = intl.formatMessage({
    defaultMessage: "Not enough points",
  })

  const isDisabled = price?.redemptions?.length && hasInsufficientPoints

  return (
    <article
      className={classNames}
      onMouseEnter={() => engage(hotel.name)}
      onMouseLeave={() => disengageAfterDelay()}
    >
      <div>
        <div className={styles.imageContainer}>
          <ImageGallery
            title={hotel.name}
            images={galleryImages}
            fill
            sizes="(min-width: 768px) calc(100vw - 340px), (min-width: 1367px) 33vw, 100vw"
          />
          {hotel.ratings?.tripAdvisor && (
            <TripAdvisorChip rating={hotel.ratings.tripAdvisor.rating} />
          )}
        </div>
      </div>
      <div className={styles.hotelContent}>
        <div className={styles.hotelInformation}>
          <div className={styles.titleContainer}>
            <HotelLogoIcon
              hotelId={hotel.operaId}
              hotelType={hotel.hotelType}
            />
            <Typography variant="Title/Subtitle/lg">
              <h2>{hotel.name}</h2>
            </Typography>
            <div className={styles.addressContainer}>
              <address className={styles.address}>
                {type == HotelCardListingTypeEnum.MapListing ? (
                  <Typography variant="Body/Supporting text (caption)/smRegular">
                    <p>{addressStr}</p>
                  </Typography>
                ) : (
                  <Link
                    size="small"
                    textDecoration="underline"
                    onClick={handleAddressClick}
                    href={mapUrl}
                    keepSearchParams
                    aria-label={intl.formatMessage({
                      defaultMessage: "See on map",
                    })}
                  >
                    <Typography variant="Body/Supporting text (caption)/smRegular">
                      <p>{addressStr}</p>
                    </Typography>
                  </Link>
                )}
              </address>

              <div>
                <Divider variant="vertical" />
              </div>
              <Typography variant="Body/Supporting text (caption)/smRegular">
                <span>
                  {intl.formatMessage(
                    {
                      defaultMessage: "{number} km to city center",
                    },
                    {
                      number: getSingleDecimal(
                        hotel.location.distanceToCentre / 1000
                      ),
                    }
                  )}
                </span>
              </Typography>
            </div>
          </div>

          {hotel.hotelContent.texts.descriptions ? (
            <Typography variant="Body/Paragraph/mdRegular">
              <p className={styles.hotelDescription}>
                {hotel.hotelContent.texts.descriptions.short}
              </p>
            </Typography>
          ) : null}

          <div className={styles.facilities}>
            {amenities.map((facility) => (
              <div className={styles.facilitiesItem} key={facility.id}>
                <FacilityToIcon id={facility.id} color="CurrentColor" />
                <Typography variant="Body/Supporting text (caption)/smRegular">
                  <span>{facility.name}</span>
                </Typography>
              </div>
            ))}
          </div>
          <ReadMore
            label={intl.formatMessage({
              defaultMessage: "See hotel details",
            })}
            hotelId={hotel.operaId}
            showCTA={true}
            sidePeekKey={SidePeekEnum.hotelDetails}
          />
        </div>
        <PricesWrapper
          pathname={selectRate(lang)}
          isClickable={availability.productType && !isDisabled}
          hotelId={hotel.operaId}
          removeBookingCodeFromSearchParams={!!(bookingCode && fullPrice)}
          searchParams={searchParams}
        >
          {!availability.productType ? (
            <NoPriceAvailableCard />
          ) : (
            <>
              {bookingCode && (
                <BookingCodeChip
                  bookingCode={bookingCode}
                  isUnavailable={fullPrice}
                />
              )}
              {(!isUserLoggedIn ||
                !price?.member ||
                (bookingCode && !fullPrice)) &&
                price?.public && (
                  <HotelPriceCard
                    productTypePrices={price.public}
                    className={styles.priceCard}
                  />
                )}
              {availability.productType.member && (
                <HotelPriceCard
                  productTypePrices={availability.productType.member}
                  className={styles.priceCard}
                  isMemberPrice
                />
              )}
              {price?.voucher && (
                <HotelVoucherCard productTypeVoucher={price.voucher} />
              )}
              {price?.bonusCheque && (
                <HotelChequeCard productTypeCheque={price.bonusCheque} />
              )}
              {price?.redemptions?.length ? (
                <div className={styles.pointsCard}>
                  <Caption>
                    {intl.formatMessage({
                      defaultMessage: "Available rates",
                    })}
                  </Caption>
                  {price.redemptions.map((redemption) => (
                    <HotelPointsRow
                      key={redemption.rateCode}
                      pointsPerStay={redemption.localPrice.pointsPerStay}
                      additionalPricePerStay={
                        redemption.localPrice.additionalPricePerStay
                      }
                      additionalPriceCurrency={
                        redemption.localPrice.currency ?? undefined
                      }
                    />
                  ))}
                </div>
              ) : null}
              {isDisabled ? (
                <div className={cx(styles.fakeButton, styles.disabled)}>
                  <Typography variant="Body/Paragraph/mdBold">
                    <span>{notEnoughPointsLabel}</span>
                  </Typography>
                </div>
              ) : (
                <div className={styles.fakeButton}>
                  <Typography variant="Body/Paragraph/mdBold">
                    <span>
                      {intl.formatMessage({
                        defaultMessage: "See rooms",
                      })}
                    </span>
                  </Typography>
                </div>
              )}
            </>
          )}
        </PricesWrapper>
      </div>
    </article>
  )
}

interface PricesWrapperProps {
  children: React.ReactNode
  isClickable?: boolean
  hotelId: string
  pathname: string
  removeBookingCodeFromSearchParams: boolean
  searchParams: ReadonlyURLSearchParams
}
function PricesWrapper({
  children,
  hotelId,
  isClickable,
  pathname,
  removeBookingCodeFromSearchParams,
  searchParams,
}: PricesWrapperProps) {
  const content = <div className={styles.prices}>{children}</div>

  if (!isClickable) {
    return content
  }

  const params = new URLSearchParams(searchParams)
  params.delete("city")
  params.set("hotel", hotelId)

  if (removeBookingCodeFromSearchParams) {
    params.delete("bookingCode")
  }

  const href = `${pathname}?${params.toString()}`

  return (
    <Link href={href} color="none" className={styles.link}>
      {content}
    </Link>
  )
}

export default memo(HotelCard)
