import { createCounter } from "@scandic-hotels/common/telemetry" import * as api from "../../../api" import { badRequestError } from "../../../errors" import { toApiLang } from "../../../utils" import { hotelsAvailabilitySchema } from "../output" import type { Lang } from "@scandic-hotels/common/constants/language" import type { HotelsAvailabilityInputSchema } from "../availability/hotelsByCity" export async function getHotelsAvailabilityByCity({ input, lang, userToken, serviceToken, userPoints = 0, }: { input: HotelsAvailabilityInputSchema lang: Lang userToken: string | null | undefined serviceToken: string userPoints: number | undefined }) { const { cityId, roomStayStartDate, roomStayEndDate, adults, children, bookingCode, redemption, } = input const apiLang = toApiLang(lang) const params = { roomStayStartDate, roomStayEndDate, adults, ...(children && { children }), ...(bookingCode && { bookingCode }), ...(redemption ? { isRedemption: "true" } : {}), language: apiLang, } satisfies Record const getHotelsAvailabilityByCityCounter = createCounter( "hotel.getHotelsAvailabilityByCity" ) const metricsGetHotelsAvailabilityByCity = getHotelsAvailabilityByCityCounter.init({ apiLang, cityId, roomStayStartDate, roomStayEndDate, adults, children, bookingCode, redemption, }) metricsGetHotelsAvailabilityByCity.start() const apiResponse = await api.get( api.endpoints.v1.Availability.city(cityId), { headers: { Authorization: `Bearer ${userToken ?? serviceToken}`, }, }, params ) if (!apiResponse.ok) { await metricsGetHotelsAvailabilityByCity.httpError(apiResponse) throw new Error("Failed to fetch hotels availability by city") } const apiJson = await apiResponse.json() const validateAvailabilityData = hotelsAvailabilitySchema.safeParse(apiJson) if (!validateAvailabilityData.success) { metricsGetHotelsAvailabilityByCity.validationError( validateAvailabilityData.error ) throw badRequestError() } if (redemption) { validateAvailabilityData.data.data.forEach((data) => { data.attributes.productType?.redemptions?.forEach((r) => { r.hasEnoughPoints = userPoints >= r.localPrice.pointsPerStay }) }) } const result = { availability: validateAvailabilityData.data.data.flatMap( (hotels) => hotels.attributes ), } metricsGetHotelsAvailabilityByCity.success() return result }