import stringify from "json-stable-stringify-without-jsonify"
import { cookies } from "next/headers"
import { notFound } from "next/navigation"
import { Suspense } from "react"

import { FamilyAndFriendsCodes } from "@scandic-hotels/common/constants/familyAndFriends"
import { TrackingSDK } from "@scandic-hotels/tracking/TrackingSDK"

import { AlternativeHotelsPageTitle } from "../components/AlternativeHotelsPageTitle"
import FnFNotAllowedAlert from "../components/FnFNotAllowedAlert"
import { SelectHotel } from "../components/SelectHotel"
import { getHotels } from "../components/SelectHotel/helpers"
import { getHotelSearchDetails } from "../misc/getHotelSearchDetails"
import { getSelectHotelTracking } from "../misc/selectHotelTracking"
import { parseSelectHotelSearchParams } from "../utils/url"

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

import type { NextSearchParams } from "../types"

export { SelectHotelSkeleton as AlternativeHotelsPageSkeleton } from "../components/SelectHotel"

export async function AlternativeHotelsPage({
  lang,
  searchParams,
}: {
  lang: Lang
  searchParams: NextSearchParams
}) {
  const booking = parseSelectHotelSearchParams(searchParams)

  if (!booking) return notFound()

  const searchDetails = await getHotelSearchDetails({
    ...booking,
    lang,
    isAlternativeHotels: true,
  })

  if (!searchDetails || !searchDetails.hotel || !searchDetails.city) {
    return notFound()
  }

  // TODO move logic to function to reuse
  if (
    booking.bookingCode &&
    FamilyAndFriendsCodes.includes(booking.bookingCode)
  ) {
    const cookieStore = await cookies()
    const isInvalidFNF = cookieStore.get("sc")?.value !== "1"

    if (isInvalidFNF) {
      return <FnFNotAllowedAlert />
    }
  }

  // TODO: This needs to be refactored into its
  // own functions
  const hotels = await getHotels({
    fromDate: booking.fromDate,
    toDate: booking.toDate,
    rooms: booking.rooms,
    isAlternativeFor: searchDetails.hotel,
    bookingCode: booking.bookingCode,
    city: searchDetails.city,
    redemption: !!searchDetails.redemption,
    lang,
  })

  const arrivalDate = new Date(booking.fromDate)
  const departureDate = new Date(booking.toDate)

  const isRedemptionAvailability = searchDetails.redemption
    ? hotels.some(
        (hotel) => hotel.availability.productType?.redemptions?.length
      )
    : false

  const isBookingCodeRateAvailable = booking.bookingCode
    ? hotels.some(
        (hotel) =>
          hotel.availability.bookingCode &&
          hotel.availability.status === "Available"
      )
    : false

  const { hotelsTrackingData, pageTrackingData } = getSelectHotelTracking({
    lang,
    pageId: searchDetails.hotel ? "alternative-hotels" : "select-hotel",
    pageName: searchDetails.hotel
      ? "hotelreservation|alternative-hotels"
      : "hotelreservation|select-hotel",
    siteSections: searchDetails.hotel
      ? "hotelreservation|alternative-hotels"
      : "hotelreservation|select-hotel",
    arrivalDate,
    departureDate,
    rooms: booking.rooms,
    hotelsResult: hotels?.length ?? 0,
    searchTerm: searchDetails.hotel
      ? booking.hotelId
      : searchDetails.cityIdentifier,
    country: hotels?.[0]?.hotel.address.country,
    hotelCity: hotels?.[0]?.hotel.address.city,
    bookingCode: booking.bookingCode,
    isBookingCodeRateAvailable,
    isRedemption: searchDetails.redemption,
    isRedemptionAvailable: isRedemptionAvailability,
  })

  const suspenseKey = stringify(searchParams)

  return (
    <>
      <SelectHotel
        bookingCode={booking.bookingCode}
        city={searchDetails.city}
        hotels={hotels}
        isAlternative={!!searchDetails.hotel}
        isBookingCodeRateAvailable={isBookingCodeRateAvailable}
        title={
          <AlternativeHotelsPageTitle hotelName={searchDetails.hotel.name} />
        }
        lang={lang}
      />
      <Suspense key={`${suspenseKey}-tracking`} fallback={null}>
        <TrackingSDK
          hotelInfo={hotelsTrackingData}
          pageData={pageTrackingData}
        />
      </Suspense>
    </>
  )
}
