import { getHotelData } from "@/lib/trpc/memoizedRequests"
import { serverClient } from "@/lib/trpc/server"

import { getLang } from "@/i18n/serverContext"

import type { AvailabilityInput } from "@/types/components/hotelReservation/selectHotel/availabilityInput"
import type { HotelData } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
import type {
  CategorizedFilters,
  Filter,
} from "@/types/components/hotelReservation/selectHotel/hotelFilters"
import type { HotelPin } from "@/types/components/hotelReservation/selectHotel/map"
import { HotelListingEnum } from "@/types/enums/hotelListing"

const hotelSurroundingsFilterNames = [
  "Hotel surroundings",
  "Hotel omgivelser",
  "Hotelumgebung",
  "Hotellia lähellä",
  "Hotellomgivelser",
  "Omgivningar",
]

export async function fetchAvailableHotels(
  input: AvailabilityInput
): Promise<HotelData[]> {
  const availableHotels = await serverClient().hotel.availability.hotels(input)

  if (!availableHotels) throw new Error()

  const language = getLang()
  const hotelMap = new Map<number, any>()

  availableHotels.availability.forEach((hotel) => {
    const existingHotel = hotelMap.get(hotel.hotelId)
    if (existingHotel) {
      if (hotel.ratePlanSet === HotelListingEnum.RatePlanSet.PUBLIC) {
        existingHotel.bestPricePerNight.regularAmount =
          hotel.bestPricePerNight?.regularAmount
      } else if (hotel.ratePlanSet === HotelListingEnum.RatePlanSet.MEMBER) {
        existingHotel.bestPricePerNight.memberAmount =
          hotel.bestPricePerNight?.memberAmount
      }
    } else {
      hotelMap.set(hotel.hotelId, { ...hotel })
    }
  })

  const hotels = Array.from(hotelMap.values()).map(async (hotel) => {
    const hotelData = await getHotelData({
      hotelId: hotel.hotelId.toString(),
      language,
    })

    if (!hotelData) throw new Error()

    return {
      hotelData: hotelData.data.attributes,
      price: hotel.bestPricePerNight,
    }
  })

  return await Promise.all(hotels)
}

export function getFiltersFromHotels(hotels: HotelData[]): CategorizedFilters {
  const filters = hotels.flatMap((hotel) => hotel.hotelData.detailedFacilities)

  const uniqueFilterIds = [...new Set(filters.map((filter) => filter.id))]
  const filterList: Filter[] = uniqueFilterIds
    .map((filterId) => filters.find((filter) => filter.id === filterId))
    .filter((filter): filter is Filter => filter !== undefined)

  return filterList.reduce<CategorizedFilters>(
    (acc, filter) => {
      if (filter.filter && hotelSurroundingsFilterNames.includes(filter.filter))
        return {
          facilityFilters: acc.facilityFilters,
          surroundingsFilters: [...acc.surroundingsFilters, filter],
        }

      return {
        facilityFilters: [...acc.facilityFilters, filter],
        surroundingsFilters: acc.surroundingsFilters,
      }
    },
    { facilityFilters: [], surroundingsFilters: [] }
  )
}
