import { notFound } from "next/navigation"

import { logger } from "@scandic-hotels/common/logger"
import { SEARCH_TYPE_REDEMPTION } from "@scandic-hotels/trpc/constants/booking"

import { SelectRate } from "../components/SelectRate"
import { getValidDates } from "../components/SelectRate/getValidDates"
import { getSelectRateTracking } from "../components/SelectRate/Tracking/tracking"
import { SelectRateProvider } from "../contexts/SelectRate/SelectRateContext"
import { getHotel } from "../trpc/memoizedRequests"
import { parseSelectRateSearchParams } from "../utils/url"

import type { Lang } from "@scandic-hotels/common/constants/language"
import type {
  TrackingSDKHotelInfo,
  TrackingSDKPageData,
} from "@scandic-hotels/common/tracking/types"

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

const rateTypeRegex = {
  ARB: /(^B[a-z]{3}\d{6}$)/,
  VOUCHER: /(^VO[0-9a-z]*$)/,
}

const singleRoomRateTypes = combineRegExps(
  [rateTypeRegex.ARB, rateTypeRegex.VOUCHER],
  "i"
)

export async function SelectRatePage({
  lang,
  searchParams,
  renderTracking,
}: {
  lang: Lang
  searchParams: NextSearchParams
  renderTracking: (trackingProps: {
    hotelsTrackingData: TrackingSDKHotelInfo
    pageTrackingData: TrackingSDKPageData
  }) => React.ReactNode
}) {
  const booking = parseSelectRateSearchParams(searchParams)

  if (!booking) {
    logger.debug("Invalid search params", searchParams)
    notFound()
  }

  const isMultiRoom = booking.rooms.length > 1
  const isRedemption = booking.searchType === SEARCH_TYPE_REDEMPTION
  const isArbOrVoucher = booking.bookingCode
    ? singleRoomRateTypes.test(booking.bookingCode)
    : false

  if ((isMultiRoom && isRedemption) || (isMultiRoom && isArbOrVoucher)) {
    logger.debug(
      "Invalid search params, can't have multiroom and redemption/voucher",
      { isMultiRoom, isRedemption, isArbOrVoucher }
    )
    notFound()
  }

  // If someone tries to update the url with
  // a bookingCode also, then we need to remove it
  if (isRedemption && searchParams.bookingCode) {
    delete searchParams.bookingCode
  }

  const hotelData = await getHotel({
    hotelId: booking.hotelId,
    isCardOnlyPayment: false,
    language: lang,
  })

  if (!hotelData) {
    logger.debug("Unable to find hotel data")
    notFound()
  }

  const { fromDate, toDate } = getValidDates(booking.fromDate, booking.toDate)

  const { rooms, searchType, bookingCode, city: paramCity } = booking

  const arrivalDate = fromDate.toDate()
  const departureDate = toDate.toDate()

  const { hotelsTrackingData, pageTrackingData } = getSelectRateTracking({
    lang,
    arrivalDate,
    departureDate,
    hotelId: hotelData.hotel.id,
    hotelName: hotelData.hotel.name,
    country: hotelData.hotel.address.country,
    hotelCity: hotelData.hotel.address.city,
    paramCity,
    bookingCode,
    isRedemption: searchType === SEARCH_TYPE_REDEMPTION,
    rooms,
  })

  return (
    <>
      <SelectRateProvider hotelData={hotelData}>
        <SelectRate hotelData={hotelData} booking={booking} />
      </SelectRateProvider>
      {renderTracking({ hotelsTrackingData, pageTrackingData })}
    </>
  )
}

function combineRegExps(regexps: RegExp[], flags = "") {
  return new RegExp(regexps.map((r) => r.source).join("|"), flags)
}
