import { cookies } from "next/headers"
import { notFound } from "next/navigation"
import { Suspense } from "react"

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

import HotelHeader from "../components/EnterDetails/Header"
import Payment from "../components/EnterDetails/Payment"
import Multiroom from "../components/EnterDetails/Room/Multiroom"
import RoomOne from "../components/EnterDetails/Room/One"
import DesktopSummary from "../components/EnterDetails/Summary/Desktop"
import MobileSummary from "../components/EnterDetails/Summary/Mobile"
import EnterDetailsTrackingWrapper from "../components/EnterDetails/Tracking"
import FnFNotAllowedAlert from "../components/FnFNotAllowedAlert"
import EnterDetailsProvider from "../contexts/EnterDetails/EnterDetailsContext"
import { RoomProvider } from "../contexts/EnterDetails/RoomContext"
import { getBreakfastPackages } from "../trpc/memoizedRequests/getBreakfastPackages"
import { getHotel } from "../trpc/memoizedRequests/getHotel"
import { getProfileSafely } from "../trpc/memoizedRequests/getProfile"
import { getSelectedRoomsAvailabilityEnterDetails } from "../trpc/memoizedRequests/getSelectedRoomsAvailabilityEnterDetails"
import { parseDetailsSearchParams } from "../utils/url"

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

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

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

export async function EnterDetailsPage({
  lang,
  searchParams,
}: {
  lang: Lang
  searchParams: NextSearchParams
}) {
  const selectRoomParams = new URLSearchParams(
    searchParams as Record<string, string>
  )

  const booking = parseDetailsSearchParams(searchParams)

  if (!booking) return notFound()

  if (selectRoomParams.has("activeRoomIndex")) {
    selectRoomParams.delete("activeRoomIndex")
  }

  if (
    booking.bookingCode &&
    FamilyAndFriendsCodes.includes(booking.bookingCode)
  ) {
    const cookieStore = await cookies()
    const isInValidFNF = cookieStore.get("sc")?.value !== "1"

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

  const breakfastInput = {
    adults: 1,
    fromDate: booking.fromDate,
    hotelId: booking.hotelId,
    toDate: booking.toDate,
  }
  const hotelInput = {
    hotelId: booking.hotelId,
    // TODO: Remove this from input since it forces
    //       waterfalls for no other reason than to
    //       set merchantInformationData.alternatePaymentOptions
    //       to an empty array
    isCardOnlyPayment: false,
    language: lang,
  }
  const getHotelPromise = getHotel(hotelInput)
  const getBreakfastPackagesPromise = getBreakfastPackages(breakfastInput)
  const getProfilePromise = getProfileSafely()

  const rooms = await getSelectedRoomsAvailabilityEnterDetails({
    booking,
    lang,
  })

  const hotelData = await getHotelPromise

  if (!hotelData || !rooms.length) {
    return notFound()
  }

  const breakfastPackages = await getBreakfastPackagesPromise
  const user = await getProfilePromise

  const isCardOnlyPayment = rooms.some((room) => room.mustBeGuaranteed)
  const { hotel } = hotelData
  // TODO: Temp fix to avoid waterfall fetch and moving this
  //       logic from the route here for now
  if (isCardOnlyPayment) {
    hotel.merchantInformationData.alternatePaymentOptions = []
  }

  const firstRoom = rooms[0]
  const multirooms = rooms.slice(1)

  const { rateDefinition, rateDefinitionMember } = firstRoom.roomRate
  if (user && rateDefinitionMember) {
    const rateCode = selectRoomParams.get("room[0].ratecode")
    if (rateDefinitionMember.rateCode !== rateCode) {
      booking.rooms[0].rateCode = rateDefinitionMember.rateCode
      selectRoomParams.set("room[0].ratecode", rateDefinitionMember.rateCode)
      booking.rooms[0].counterRateCode = rateDefinition.rateCode
      selectRoomParams.set("room[0].counterratecode", rateDefinition.rateCode)
    }
  }

  // attribute data-footer-spacing used to add spacing
  // beneath footer to be able to show entire footer upon
  // scrolling down to the bottom of the page
  return (
    <main data-footer-spacing>
      <EnterDetailsProvider
        booking={booking}
        breakfastPackages={breakfastPackages}
        lang={lang}
        rooms={rooms}
        searchParamsStr={selectRoomParams.toString()}
        user={user}
        vat={hotel.vat}
        roomCategories={hotelData.roomCategories}
      >
        <HotelHeader hotelData={hotelData} />
        <div className={styles.container}>
          <div className={styles.content}>
            <RoomProvider idx={0} room={firstRoom}>
              <RoomOne user={user} />
            </RoomProvider>
            {multirooms.map((room, idx) => (
              // Need to start idx from 1 since first room is
              // rendered above
              <RoomProvider key={idx + 1} idx={idx + 1} room={room}>
                <Multiroom />
              </RoomProvider>
            ))}
            <Suspense>
              <Payment
                otherPaymentOptions={
                  hotel.merchantInformationData.alternatePaymentOptions
                }
                supportedCards={hotel.merchantInformationData.cards}
              />
            </Suspense>
          </div>
          <aside className={styles.summary}>
            <MobileSummary isUserLoggedIn={!!user} />
            <DesktopSummary isUserLoggedIn={!!user} />
          </aside>
        </div>

        <EnterDetailsTrackingWrapper
          booking={booking}
          hotel={hotel}
          isMember={!!user}
          lang={lang}
          rooms={rooms}
        />
      </EnterDetailsProvider>
    </main>
  )
}
