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 { Package, Packages } from "@scandic-hotels/trpc/types/packages"
import type { JSX } from "react"

import type { RoomPackageCodes } from "../../types/components/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 filterOverlappingDates<
  T extends {
    startDate: Date | Dayjs | string | undefined | null
    endDate: Date | Dayjs | string | undefined | null
  },
>(dateRangeItems: T[], fromDate: Date | Dayjs, toDate: Date | Dayjs) {
  const startDate = dt(fromDate)
  const endDate = dt(toDate)

  return dateRangeItems.filter((item) =>
    hasOverlappingDates(item, startDate, endDate)
  )
}

export function hasOverlappingDates(
  dateRangeItem: {
    startDate: Date | Dayjs | string | undefined | null
    endDate: Date | Dayjs | string | undefined | null
  },
  fromDate: Date | Dayjs,
  toDate: Date | Dayjs
) {
  const startDate = dt(fromDate)
  const endDate = dt(toDate)

  if (dateRangeItem.endDate && dateRangeItem.startDate) {
    const itemStartDate = dt(dateRangeItem.startDate)
    const itemEndDate = dt(dateRangeItem.endDate)

    const fromDateIsBetweenItemDates = startDate.isBetween(
      itemStartDate,
      itemEndDate,
      "date",
      "[]"
    )
    const toDateIsBetweenItemDates = endDate.isBetween(
      itemStartDate,
      itemEndDate,
      "date",
      "[]"
    )

    const itemFullyContained =
      startDate.isSameOrBefore(itemStartDate, "date") &&
      endDate.isSameOrAfter(itemEndDate, "date")

    return (
      fromDateIsBetweenItemDates ||
      toDateIsBetweenItemDates ||
      itemFullyContained
    )
  }
  return true
}
