import "./enterDetailsLayout.css"

import { notFound } from "next/navigation"

import {
  getBreakfastPackages,
  getCreditCardsSafely,
  getHotelData,
  getProfileSafely,
  getSelectedRoomAvailability,
} from "@/lib/trpc/memoizedRequests"

import BedType from "@/components/HotelReservation/EnterDetails/BedType"
import Breakfast from "@/components/HotelReservation/EnterDetails/Breakfast"
import Details from "@/components/HotelReservation/EnterDetails/Details"
import HistoryStateManager from "@/components/HotelReservation/EnterDetails/HistoryStateManager"
import Payment from "@/components/HotelReservation/EnterDetails/Payment"
import SectionAccordion from "@/components/HotelReservation/EnterDetails/SectionAccordion"
import SelectedRoom from "@/components/HotelReservation/EnterDetails/SelectedRoom"
import {
  generateChildrenString,
  getQueryParamsForEnterDetails,
} from "@/components/HotelReservation/SelectRate/RoomSelection/utils"
import { getIntl } from "@/i18n"
import StepsProvider from "@/providers/StepsProvider"

import { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
import { StepEnum } from "@/types/enums/step"
import type { LangParams, PageArgs } from "@/types/params"

function isValidStep(step: string): step is StepEnum {
  return Object.values(StepEnum).includes(step as StepEnum)
}

export default async function StepPage({
  params: { lang },
  searchParams,
}: PageArgs<LangParams, SelectRateSearchParams & { step: StepEnum }>) {
  const intl = await getIntl()
  const selectRoomParams = new URLSearchParams(searchParams)
  selectRoomParams.delete("step")
  const searchParamsString = selectRoomParams.toString()
  const {
    hotel: hotelId,
    rooms,
    fromDate,
    toDate,
  } = getQueryParamsForEnterDetails(selectRoomParams)

  const {
    adults,
    children,
    roomTypeCode,
    rateCode,
    packages: packageCodes,
  } = rooms[0] // TODO: Handle multiple rooms

  const childrenAsString = children && generateChildrenString(children)

  const breakfastInput = { adults, fromDate, hotelId, toDate }
  void getBreakfastPackages(breakfastInput)
  void getSelectedRoomAvailability({
    hotelId,
    adults,
    children: childrenAsString,
    roomStayStartDate: fromDate,
    roomStayEndDate: toDate,
    rateCode,
    roomTypeCode,
    packageCodes,
  })

  const roomAvailability = await getSelectedRoomAvailability({
    hotelId,
    adults,
    children: childrenAsString,
    roomStayStartDate: fromDate,
    roomStayEndDate: toDate,
    rateCode,
    roomTypeCode,
    packageCodes,
  })
  const hotelData = await getHotelData({
    hotelId,
    language: lang,
    isCardOnlyPayment: roomAvailability?.mustBeGuaranteed,
  })
  const breakfastPackages = await getBreakfastPackages(breakfastInput)
  const user = await getProfileSafely()
  const savedCreditCards = await getCreditCardsSafely()

  if (!isValidStep(searchParams.step) || !hotelData || !roomAvailability) {
    return notFound()
  }

  const mustBeGuaranteed = roomAvailability?.mustBeGuaranteed ?? false

  const paymentGuarantee = intl.formatMessage({
    id: "Payment Guarantee",
  })
  const payment = intl.formatMessage({
    id: "Payment",
  })
  const guaranteeWithCard = intl.formatMessage({
    id: "Guarantee booking with credit card",
  })
  const selectPaymentMethod = intl.formatMessage({
    id: "Select payment method",
  })

  const roomPrice = {
    memberPrice: roomAvailability.memberRate?.localPrice.pricePerStay,
    publicPrice: roomAvailability.publicRate!.localPrice.pricePerStay,
  }

  const memberPrice = roomAvailability.memberRate
    ? {
        price: roomAvailability.memberRate.localPrice.pricePerStay,
        currency: roomAvailability.memberRate.localPrice.currency,
      }
    : undefined

  return (
    <StepsProvider
      bedTypes={roomAvailability.bedTypes}
      breakfastPackages={breakfastPackages}
      isMember={!!user}
      searchParams={searchParamsString}
      step={searchParams.step}
    >
      <section>
        <HistoryStateManager />
        <SelectedRoom
          hotelId={hotelId}
          room={roomAvailability.selectedRoom}
          rateDescription={roomAvailability.cancellationText}
        />

        {/* TODO: How to handle no beds found? */}
        {roomAvailability.bedTypes ? (
          <SectionAccordion
            header={intl.formatMessage({ id: "Select bed" })}
            step={StepEnum.selectBed}
            label={intl.formatMessage({ id: "Request bedtype" })}
          >
            <BedType bedTypes={roomAvailability.bedTypes} />
          </SectionAccordion>
        ) : null}

        {breakfastPackages?.length ? (
          <SectionAccordion
            header={intl.formatMessage({ id: "Food options" })}
            step={StepEnum.breakfast}
            label={intl.formatMessage({ id: "Select breakfast options" })}
          >
            <Breakfast packages={breakfastPackages} />
          </SectionAccordion>
        ) : null}

        <SectionAccordion
          header={intl.formatMessage({ id: "Details" })}
          step={StepEnum.details}
          label={intl.formatMessage({ id: "Enter your details" })}
        >
          <Details user={user} memberPrice={memberPrice} />
        </SectionAccordion>

        <SectionAccordion
          header={mustBeGuaranteed ? paymentGuarantee : payment}
          step={StepEnum.payment}
          label={mustBeGuaranteed ? guaranteeWithCard : selectPaymentMethod}
        >
          <Payment
            user={user}
            roomPrice={roomPrice}
            otherPaymentOptions={
              hotelData.data.attributes.merchantInformationData
                .alternatePaymentOptions
            }
            savedCreditCards={savedCreditCards}
            mustBeGuaranteed={mustBeGuaranteed}
          />
        </SectionAccordion>
      </section>
    </StepsProvider>
  )
}
