import { notFound } from "next/navigation"

import { env } from "@/env/server"
import { getCityCoordinates } from "@/lib/trpc/memoizedRequests"

import TrackingSDK from "@/components/TrackingSDK"
import { getLang } from "@/i18n/serverContext"
import { getHotelSearchDetails } from "@/utils/hotelSearchDetails"
import { safeTry } from "@/utils/safeTry"

import { getHotelPins } from "../../HotelCardDialogListing/utils"
import { getFiltersFromHotels, getHotels } from "../helpers"
import { getTracking } from "./tracking"
import SelectHotelMap from "."

import type { SelectHotelMapContainerProps } from "@/types/components/hotelReservation/selectHotel/map"

export async function SelectHotelMapContainer({
  booking,
  isAlternativeHotels,
}: SelectHotelMapContainerProps) {
  const lang = await getLang()
  const googleMapId = env.GOOGLE_DYNAMIC_MAP_ID
  const googleMapsApiKey = env.GOOGLE_STATIC_MAP_KEY
  const getHotelSearchDetailsPromise = safeTry(
    getHotelSearchDetails(booking, isAlternativeHotels)
  )

  const [searchDetails] = await getHotelSearchDetailsPromise

  if (!searchDetails) {
    return notFound()
  }

  const {
    adultsInRoom,
    bookingCode,
    childrenInRoom,
    city,
    cityName,
    hotel: isAlternativeFor,
    noOfRooms,
    redemption,
  } = searchDetails

  if (!city) {
    return notFound()
  }

  const hotels = await getHotels({
    fromDate: booking.fromDate,
    toDate: booking.toDate,
    rooms: booking.rooms,
    isAlternativeFor,
    bookingCode,
    city,
    redemption: !!redemption,
  })

  const hotelPins = getHotelPins(hotels)
  const filterList = getFiltersFromHotels(hotels)
  const cityCoordinates = await getCityCoordinates({
    city: city.name,
    hotel: { address: hotels?.[0]?.hotel?.address.streetAddress },
  })

  const arrivalDate = new Date(booking.fromDate)
  const departureDate = new Date(booking.toDate)
  const isRedemptionAvailability = redemption
    ? hotels.some(
        (hotel) => hotel.availability.productType?.redemptions?.length
      )
    : false

  const isBookingCodeRateAvailable = bookingCode
    ? hotels?.some((hotel) => hotel.availability.bookingCode)
    : false

  const { hotelsTrackingData, pageTrackingData } = getTracking(
    lang,
    !!isAlternativeFor,
    !!isAlternativeHotels,
    arrivalDate,
    departureDate,
    adultsInRoom,
    childrenInRoom,
    hotels.length,
    booking.hotelId,
    noOfRooms,
    hotels?.[0]?.hotel.address.country,
    hotels?.[0]?.hotel.address.city,
    cityName,
    bookingCode,
    isBookingCodeRateAvailable,
    redemption,
    isRedemptionAvailability
  )

  return (
    <>
      <SelectHotelMap
        apiKey={googleMapsApiKey}
        hotelPins={hotelPins}
        mapId={googleMapId}
        hotels={hotels}
        filterList={filterList}
        cityCoordinates={cityCoordinates}
        bookingCode={bookingCode ?? ""}
        isBookingCodeRateAvailable={isBookingCodeRateAvailable}
      />
      <TrackingSDK pageData={pageTrackingData} hotelInfo={hotelsTrackingData} />
    </>
  )
}
