"use client"

import { useParams } from "next/dist/client/components/navigation"
import { useRouter, useSearchParams } from "next/navigation"
import { memo } from "react"
import { useIntl } from "react-intl"

import DiscountIcon from "@scandic-hotels/design-system/Icons/DiscountIcon"
import HotelLogoIcon from "@scandic-hotels/design-system/Icons/HotelLogoIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"

import { selectHotelMap, selectRate } from "@/constants/routes/hotelReservation"
import { useHotelsMapStore } from "@/stores/hotels-map"

import { FacilityToIcon } from "@/components/ContentType/HotelPage/data"
import ImageGallery from "@/components/ImageGallery"
import Button from "@/components/TempDesignSystem/Button"
import Divider from "@/components/TempDesignSystem/Divider"
import IconChip from "@/components/TempDesignSystem/IconChip"
import Link from "@/components/TempDesignSystem/Link"
import Body from "@/components/TempDesignSystem/Text/Body"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import { Tooltip } from "@/components/TempDesignSystem/Tooltip"
import { mapApiImagesToGalleryImages } from "@/utils/imageGallery"
import { getSingleDecimal } from "@/utils/numberFormatting"

import ReadMore from "../ReadMore"
import TripAdvisorChip from "../TripAdvisorChip"
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 { HotelCardListingTypeEnum } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
import type { HotelCardProps } from "@/types/components/hotelReservation/selectHotel/hotelCardProps"
import { RateTypeEnum } from "@/types/enums/rateType"
import type { Lang } from "@/constants/languages"

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

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

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

  const handleAddressClick = (event: React.MouseEvent) => {
    event.preventDefault()
    activate(hotel.name)
    router.push(`${selectHotelMap(lang)}?${searchParams.toString()}`)
  }

  const addressStr = `${hotel.address.streetAddress}, ${hotel.address.city}`
  const galleryImages = mapApiImagesToGalleryImages(hotel.galleryImages || [])
  const fullPrice =
    availability.productType?.public?.rateType === RateTypeEnum.Regular ||
    availability.productType?.member?.rateType === RateTypeEnum.Regular
  const price = availability.productType

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

  return (
    <article
      className={classNames}
      onMouseEnter={() => engage(hotel.name)}
      onMouseLeave={() => disengageAfterDelay()}
    >
      <div>
        <div className={styles.imageContainer}>
          <ImageGallery title={hotel.name} images={galleryImages} fill />
          {hotel.ratings?.tripAdvisor && (
            <TripAdvisorChip rating={hotel.ratings.tripAdvisor.rating} />
          )}
        </div>
      </div>
      <div className={styles.hotelContent}>
        <section className={styles.hotelInformation}>
          <div className={styles.titleContainer}>
            <HotelLogoIcon
              hotelId={hotel.operaId}
              hotelType={hotel.hotelType}
            />
            <Subtitle textTransform="capitalize" color="uiTextHighContrast">
              {hotel.name}
            </Subtitle>
            <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"
                    color="burgundy"
                    variant="underscored"
                    onClick={handleAddressClick}
                    href={selectHotelMap(lang)}
                    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" color="subtle" />
              </div>
              <Caption color="uiTextPlaceholder">
                {intl.formatMessage(
                  {
                    defaultMessage: "{number} km to city center",
                  },
                  {
                    number: getSingleDecimal(
                      hotel.location.distanceToCentre / 1000
                    ),
                  }
                )}
              </Caption>
            </div>
          </div>
          <Body className={styles.hotelDescription}>
            {hotel.hotelContent.texts.descriptions?.short}
          </Body>
          <div className={styles.facilities}>
            {amenities.map((facility) => {
              const Icon = (
                <FacilityToIcon id={facility.id} color="Icon/Default" />
              )
              return (
                <div className={styles.facilitiesItem} key={facility.id}>
                  {Icon && Icon}
                  <Caption color="uiTextMediumContrast">
                    {facility.name}
                  </Caption>
                </div>
              )
            })}
          </div>
          <ReadMore
            label={intl.formatMessage({
              defaultMessage: "See hotel details",
            })}
            hotelId={hotel.operaId}
            hotel={hotel}
            showCTA={true}
          />
        </section>
        <div className={styles.prices}>
          {!availability.productType ? (
            <NoPriceAvailableCard />
          ) : (
            <>
              {bookingCode && (
                <div className={`${fullPrice ? styles.strikedText : ""}`}>
                  <Typography variant="Body/Supporting text (caption)/smRegular">
                    <IconChip
                      color="blue"
                      icon={<DiscountIcon color="Icon/Feedback/Information" />}
                    >
                      {intl.formatMessage(
                        {
                          defaultMessage:
                            "<strong>Booking code</strong>: {value}",
                        },
                        {
                          value: bookingCode,
                          strong: (text) => (
                            <Typography variant="Body/Supporting text (caption)/smBold">
                              <strong>{text}</strong>
                            </Typography>
                          ),
                        }
                      )}
                    </IconChip>
                  </Typography>
                </div>
              )}
              {(!isUserLoggedIn ||
                !price?.member ||
                (bookingCode && !fullPrice)) &&
                price?.public && (
                  <HotelPriceCard productTypePrices={price.public} />
                )}
              {availability.productType.member && (
                <HotelPriceCard
                  productTypePrices={availability.productType.member}
                  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}
              {price?.redemptions?.length && hasInsufficientPoints ? (
                <Tooltip
                  arrow="left"
                  position="bottom"
                  text={notEnoughPointsLabel}
                >
                  <Button
                    theme="base"
                    intent="primary"
                    size="small"
                    className={styles.button}
                    disabled
                  >
                    {notEnoughPointsLabel}
                  </Button>
                </Tooltip>
              ) : (
                <Button
                  asChild
                  theme="base"
                  intent="primary"
                  size="small"
                  className={styles.button}
                >
                  <Link
                    href={`${selectRate(lang)}?hotel=${hotel.operaId}`}
                    color="none"
                    keepSearchParams
                  >
                    {intl.formatMessage({
                      defaultMessage: "See rooms",
                    })}
                  </Link>
                </Button>
              )}
            </>
          )}
        </div>
      </div>
    </article>
  )
}

export default memo(HotelCard)
