import { type Dayjs, dt } from "@scandic-hotels/common/dt"
import {
  MaterialIcon,
  type MaterialIconSetIconProps,
} from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { ChildBedMapEnum } from "@scandic-hotels/trpc/enums/childBedMapEnum"
import { ChildBedTypeEnum } from "@scandic-hotels/trpc/enums/childBedTypeEnum"
import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"

import type { specialAlertsSchema } from "@scandic-hotels/trpc/routers/hotels/schemas/hotel/specialAlerts"
import type { Package, Packages } from "@scandic-hotels/trpc/types/packages"
import type { JSX } from "react"

import { type RoomPackageCodes } from "@/types/components/hotelReservation/selectRate/roomFilter"

interface IconForFeatureCodeProps {
  featureCode: RoomPackageCodes
}
export function IconForFeatureCode({
  featureCode,
  ...props
}: IconForFeatureCodeProps & MaterialIconSetIconProps): JSX.Element {
  switch (featureCode) {
    case RoomPackageCodeEnum.ACCESSIBILITY_ROOM:
      return <MaterialIcon icon="accessible" {...props} />
    case RoomPackageCodeEnum.ALLERGY_ROOM:
      return <MaterialIcon icon="mode_fan" {...props} />
    case RoomPackageCodeEnum.PET_ROOM:
    default:
      return <MaterialIcon icon="pets" {...props} />
  }
}

export const invertedBedTypeMap: Record<ChildBedTypeEnum, string> = {
  [ChildBedTypeEnum.ParentsBed]: ChildBedMapEnum[ChildBedMapEnum.IN_ADULTS_BED],
  [ChildBedTypeEnum.Crib]: ChildBedMapEnum[ChildBedMapEnum.IN_CRIB],
  [ChildBedTypeEnum.ExtraBed]: ChildBedMapEnum[ChildBedMapEnum.IN_EXTRA_BED],
  [ChildBedTypeEnum.Unknown]: ChildBedMapEnum[ChildBedMapEnum.UNKNOWN],
}

export function sumPackages(
  packages: Pick<Package, "localPrice">[] | undefined | null
) {
  if (!packages || !packages.length) {
    return {
      currency: undefined,
      price: 0,
    }
  }
  return packages.reduce(
    (total, pkg) => {
      total.price = total.price + pkg.localPrice.totalPrice
      return total
    },
    {
      currency: packages[0].localPrice.currency,
      price: 0,
    }
  )
}

export function sumPackagesRequestedPrice(packages: Packages | null) {
  if (!packages || !packages.length) {
    return {
      currency: undefined,
      price: 0,
    }
  }
  return packages.reduce(
    (total, pkg) => {
      total.price = total.price + pkg.requestedPrice.totalPrice
      return total
    },
    {
      currency: packages[0].requestedPrice.currency,
      price: 0,
    }
  )
}

export function calculateVat(priceInclVat: number, vat: number) {
  const vatPercentage = vat / 100
  const priceExclVat = priceInclVat / (1 + vatPercentage)
  const vatAmount = priceInclVat - priceExclVat
  return {
    priceExclVat,
    vatAmount,
  }
}

export function getHotelAlertsForBookingDates(
  specialAlerts: Zod.infer<typeof specialAlertsSchema>,
  fromDate: Date | Dayjs,
  toDate: Date | Dayjs
) {
  return specialAlerts.filter((alert) => {
    if (alert.endDate && alert.startDate) {
      const alertStartDate = dt(alert.startDate)
      const alertEndDate = dt(alert.endDate)
      const bookingStart = dt(fromDate)
      const bookingEnd = dt(toDate)

      const fromDateIsBetweenAlertDates = bookingStart.isBetween(
        alertStartDate,
        alertEndDate,
        "date",
        "[]"
      )
      const toDateIsBetweenAlertDates = bookingEnd.isBetween(
        alertStartDate,
        alertEndDate,
        "date",
        "[]"
      )

      const bookingFullyContainsAlert =
        bookingStart.isSameOrBefore(alertStartDate, "date") &&
        bookingEnd.isSameOrAfter(alertEndDate, "date")

      return (
        fromDateIsBetweenAlertDates ||
        toDateIsBetweenAlertDates ||
        bookingFullyContainsAlert
      )
    }
    return true
  })
}
