import type {
  CategorizedFilters,
  Filter,
  SortItem,
} from "@/types/components/destinationFilterAndSort"
import { SortOption } from "@/types/enums/destinationFilterAndSort"
import type { DestinationPagesHotelData } from "@/types/hotel"
import type { DestinationCityListItem } from "@/types/trpc/routers/contentstack/destinationCityPage"

const HOTEL_SORTING_STRATEGIES: Partial<
  Record<
    SortOption,
    (a: DestinationPagesHotelData, b: DestinationPagesHotelData) => number
  >
> = {
  [SortOption.Name]: function (a, b) {
    return a.hotel.name.localeCompare(b.hotel.name)
  },
  [SortOption.TripAdvisorRating]: function (a, b) {
    return (b.hotel.tripadvisor ?? 0) - (a.hotel.tripadvisor ?? 0)
  },
  [SortOption.Distance]: function (a, b) {
    return a.hotel.location.distanceToCentre - b.hotel.location.distanceToCentre
  },
}

const CITY_SORTING_STRATEGIES: Partial<
  Record<
    SortOption,
    (a: DestinationCityListItem, b: DestinationCityListItem) => number
  >
> = {
  [SortOption.Name]: function (a, b) {
    return a.cityName.localeCompare(b.cityName)
  },
  [SortOption.Recommended]: function (a, b) {
    if (a.sort_order === null && b.sort_order === null) {
      return a.cityName.localeCompare(b.cityName)
    }
    if (a.sort_order === null) {
      return 1
    }
    if (b.sort_order === null) {
      return -1
    }
    return b.sort_order - a.sort_order
  },
}

export function getFilteredHotels(
  hotels: DestinationPagesHotelData[],
  filters: string[]
) {
  if (filters.length) {
    return hotels.filter(({ hotel }) =>
      filters.every((filter) =>
        hotel.detailedFacilities.some((facility) => facility.slug === filter)
      )
    )
  }
  return hotels
}

export function getFilteredCities(
  filteredHotels: DestinationPagesHotelData[],
  cities: DestinationCityListItem[]
) {
  const filteredCityIdentifiers = filteredHotels.map(
    (hotel) => hotel.hotel.cityIdentifier
  )

  return cities.filter(
    (city) =>
      city.destination_settings.city &&
      filteredCityIdentifiers.includes(city.destination_settings.city)
  )
}

export function getSortedCities(
  cities: DestinationCityListItem[],
  sortOption: SortOption
) {
  const sortFn = CITY_SORTING_STRATEGIES[sortOption]
  return sortFn ? cities.sort(sortFn) : cities
}

export function getSortedHotels(
  hotels: DestinationPagesHotelData[],
  sortOption: SortOption
) {
  const sortFn = HOTEL_SORTING_STRATEGIES[sortOption]
  return sortFn ? hotels.sort(sortFn) : hotels
}

export function isValidSortOption(
  value: string,
  sortItems: SortItem[]
): value is SortOption {
  return sortItems.map((item) => item.value).includes(value as SortOption)
}

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

const HOTEL_FACILITIES_FILTER_TYPE_NAMES = [
  "Hotel facilities",
  "Hotellfaciliteter",
  "Hotelfaciliteter",
  "Hotel faciliteter",
  "Hotel-Infos",
  "Hotellin palvelut",
]

export function getFiltersFromHotels(
  hotels: DestinationPagesHotelData[]
): CategorizedFilters {
  if (hotels.length === 0) {
    return { facilityFilters: [], surroundingsFilters: [] }
  }

  const filters = hotels.flatMap(({ hotel }) => hotel.detailedFacilities)
  const sortedFilters = filters.sort((a, b) => b.sortOrder - a.sortOrder)
  const uniqueFilterNames = [
    ...new Set(sortedFilters.map((filter) => filter.name)),
  ]
  const filterList = uniqueFilterNames
    .map((filterName) => {
      const filter = filters.find((filter) => filter.name === filterName)
      return filter
        ? {
            name: filter.name,
            slug: filter.slug,
            filterType: filter.filter,
          }
        : null
    })
    .filter((filter): filter is Filter => !!filter)

  return {
    facilityFilters: filterList.filter((filter) =>
      HOTEL_FACILITIES_FILTER_TYPE_NAMES.includes(filter.filterType)
    ),
    surroundingsFilters: filterList.filter((filter) =>
      HOTEL_SURROUNDINGS_FILTER_TYPE_NAMES.includes(filter.filterType)
    ),
  }
}

export function getBasePathNameWithoutFilters(
  pathname: string,
  filterSlugs: string[]
) {
  const pathSegments = pathname.split("/")
  const filteredSegments = pathSegments.filter(
    (segment) => !filterSlugs.includes(segment)
  )
  return filteredSegments.join("/")
}
