import { useIntl } from "react-intl"

import { RateEnum } from "@scandic-hotels/common/constants/rate"
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
import Body from "@scandic-hotels/design-system/Body"
import Caption from "@scandic-hotels/design-system/Caption"
import Footnote from "@scandic-hotels/design-system/Footnote"
import { OldDSButton as Button } from "@scandic-hotels/design-system/OldDSButton"
import Subtitle from "@scandic-hotels/design-system/Subtitle"

import SignupPromoDesktop from "@/components/HotelReservation/SignupPromo/Desktop"
import { useIsUserLoggedIn } from "@/hooks/useIsUserLoggedIn"

import { isBookingCodeRate } from "./utils"

import styles from "./rateSummary.module.css"

import type { useSelectRateContext } from "@/contexts/SelectRate/SelectRateContext"
import type { SelectedRate } from "@/contexts/SelectRate/types"

export function DesktopSummary({
  input,
  selectedRates,
  isSubmitting,
  bookingCode,
}: {
  selectedRates: ReturnType<typeof useSelectRateContext>["selectedRates"]
  isSubmitting: boolean
  input: ReturnType<typeof useSelectRateContext>["input"]
  bookingCode: string
}) {
  const intl = useIntl()
  const isUserLoggedIn = useIsUserLoggedIn()

  if (!selectedRates.totalPrice) {
    return null
  }

  const hasMemberRates = selectedRates.rates.some(
    (rate) => rate && "member" in rate && rate.member
  )
  const showMemberDiscountBanner = hasMemberRates && !isUserLoggedIn

  const totalNights = intl.formatMessage(
    {
      defaultMessage: "{totalNights, plural, one {# night} other {# nights}}",
    },
    { totalNights: input.nights }
  )
  const totalAdults = intl.formatMessage(
    {
      defaultMessage: "{totalAdults, plural, one {# adult} other {# adults}}",
    },
    {
      totalAdults:
        input.data?.booking.rooms.reduce((acc, room) => acc + room.adults, 0) ??
        0,
    }
  )
  const childrenInOneOrMoreRooms = input.data?.booking.rooms.some(
    (room) => room.childrenInRoom?.length
  )
  const childrenInroom = intl.formatMessage(
    {
      defaultMessage:
        "{totalChildren, plural, one {# child} other {# children}}",
    },
    {
      totalChildren: input.data?.booking.rooms.reduce(
        (acc, room) => acc + (room.childrenInRoom?.length ?? 0),
        0
      ),
    }
  )

  const totalChildren = childrenInOneOrMoreRooms ? `, ${childrenInroom}` : ""
  const totalRooms = intl.formatMessage(
    {
      defaultMessage: "{totalRooms, plural, one {# room} other {# rooms}}",
    },
    { totalRooms: input.roomCount }
  )
  const summaryPriceText = `${totalNights}, ${totalAdults}${totalChildren}, ${totalRooms}`
  const isAllRoomsSelected = selectedRates.state === "ALL_SELECTED"

  const showDiscounted =
    isUserLoggedIn || selectedRates.rates.some(isBookingCodeRate)

  const mainRoomRate = selectedRates.rates.at(0)
  let mainRoomCurrency = getRoomCurrency(mainRoomRate)

  const totalRegularPrice = selectedRates.totalPrice.local?.regularPrice
    ? selectedRates.totalPrice.local.regularPrice
    : 0
  const isTotalRegularPriceGreaterThanPrice =
    totalRegularPrice > selectedRates.totalPrice.local.price
  const showStrikedThroughPrice =
    (!!bookingCode || isUserLoggedIn) && isTotalRegularPriceGreaterThanPrice

  return (
    <>
      <div className={styles.summaryText}>
        {selectedRates.rates.map((room, index) => {
          return (
            <RateSummary
              key={index}
              room={room}
              roomIndex={index}
              isMultiRoom={selectedRates.rates.length > 1}
            />
          )
        })}
      </div>
      <div className={styles.summaryPriceContainer}>
        {showMemberDiscountBanner && (
          <div className={styles.promoContainer}>
            <SignupPromoDesktop
              memberPrice={{
                amount: selectedRates.rates.reduce((total, rate) => {
                  if (!rate) {
                    return total
                  }

                  const memberExists = "member" in rate && rate.member
                  const publicExists = "public" in rate && rate.public
                  if (!memberExists && !publicExists) {
                    return total
                  }
                  const price =
                    rate.member?.localPrice.pricePerStay ||
                    rate.public?.localPrice.pricePerStay
                  if (!price) {
                    return total
                  }
                  const selectedPackagesPrice =
                    rate.roomInfo.selectedPackages.reduce(
                      (acc, pkg) => acc + pkg.localPrice.totalPrice,
                      0
                    )
                  return total + price + selectedPackagesPrice
                }, 0),
                currency: mainRoomCurrency ?? "",
              }}
            />
          </div>
        )}
        <div className={styles.summaryPriceTextDesktop}>
          <Body>
            {intl.formatMessage(
              {
                defaultMessage: "<b>Total price</b> (incl VAT)",
              },
              { b: (str) => <b>{str}</b> }
            )}
          </Body>
          <Caption color="uiTextMediumContrast">{summaryPriceText}</Caption>
        </div>
        <div className={styles.summaryPrice}>
          <div className={styles.summaryPriceTextDesktop}>
            <Subtitle
              color={showDiscounted ? "red" : "uiTextHighContrast"}
              textAlign="right"
            >
              {formatPrice(
                intl,
                selectedRates.totalPrice.local.price,
                selectedRates.totalPrice.local.currency,
                selectedRates.totalPrice.local.additionalPrice,
                selectedRates.totalPrice.local.additionalPriceCurrency
              )}
            </Subtitle>
            {showStrikedThroughPrice &&
              selectedRates.totalPrice.local.regularPrice && (
                <Caption
                  textAlign="right"
                  color="uiTextMediumContrast"
                  striked={true}
                >
                  {formatPrice(
                    intl,
                    selectedRates.totalPrice.local.regularPrice,
                    selectedRates.totalPrice.local.currency
                  )}
                </Caption>
              )}
            {selectedRates.totalPrice.requested ? (
              <Body color="uiTextMediumContrast">
                {intl.formatMessage(
                  {
                    defaultMessage: "Approx. {value}",
                  },
                  {
                    value: formatPrice(
                      intl,
                      selectedRates.totalPrice.requested.price,
                      selectedRates.totalPrice.requested.currency,
                      selectedRates.totalPrice.requested.additionalPrice,
                      selectedRates.totalPrice.requested.additionalPriceCurrency
                    ),
                  }
                )}
              </Body>
            ) : null}
          </div>
          <div className={styles.summaryPriceTextMobile}>
            <Caption color="uiTextHighContrast">
              {intl.formatMessage({
                defaultMessage: "Total price",
              })}
            </Caption>
            <Subtitle color={showDiscounted ? "red" : "uiTextHighContrast"}>
              {formatPrice(
                intl,
                selectedRates.totalPrice.local.price,
                selectedRates.totalPrice.local.currency,
                selectedRates.totalPrice.local.additionalPrice,
                selectedRates.totalPrice.local.additionalPriceCurrency
              )}
            </Subtitle>
            <Footnote
              color="uiTextMediumContrast"
              className={styles.summaryPriceTextMobile}
            >
              {summaryPriceText}
            </Footnote>
          </div>
          <Button
            className={styles.continueButton}
            disabled={!isAllRoomsSelected || isSubmitting}
            theme="base"
            type="submit"
          >
            {intl.formatMessage({
              defaultMessage: "Continue",
            })}
          </Button>
        </div>
      </div>
    </>
  )
}

function RateSummary({
  roomIndex,
  room,
  isMultiRoom,
}: {
  room: SelectedRate | undefined
  roomIndex: number
  isMultiRoom: boolean
}) {
  const intl = useIntl()
  const getRateDetails = useRateDetails()

  if (!room || !room.isSelected) {
    return (
      <div key={`unselected-${roomIndex}`}>
        <Subtitle color="uiTextPlaceholder">
          {intl.formatMessage(
            {
              defaultMessage: "Room {roomIndex}",
            },
            { roomIndex: roomIndex + 1 }
          )}
        </Subtitle>
        <Body color="uiTextPlaceholder">
          {intl.formatMessage({
            defaultMessage: "Select room",
          })}
        </Body>
      </div>
    )
  }

  return (
    <div key={roomIndex}>
      {isMultiRoom ? (
        <>
          <Subtitle color="uiTextHighContrast">
            {intl.formatMessage(
              {
                defaultMessage: "Room {roomIndex}",
              },
              { roomIndex: roomIndex + 1 }
            )}
          </Subtitle>
          <Body color="uiTextMediumContrast">{room.roomInfo.roomType}</Body>
          <Caption color="uiTextMediumContrast">
            {getRateDetails(room.rate)}
          </Caption>
        </>
      ) : (
        <>
          <Subtitle color="uiTextHighContrast">
            {room.roomInfo.roomType}
          </Subtitle>
          <Body color="uiTextMediumContrast">{getRateDetails(room.rate)}</Body>
        </>
      )}
    </div>
  )
}

function useRateDetails() {
  const intl = useIntl()
  const freeCancelation = intl.formatMessage({
    defaultMessage: "Free cancellation",
  })
  const nonRefundable = intl.formatMessage({
    defaultMessage: "Non-refundable",
  })
  const freeBooking = intl.formatMessage({
    defaultMessage: "Free rebooking",
  })
  const payLater = intl.formatMessage({
    defaultMessage: "Pay later",
  })
  const payNow = intl.formatMessage({
    defaultMessage: "Pay now",
  })

  return (rate: RateEnum) => {
    switch (rate) {
      case RateEnum.change:
        return `${freeBooking}, ${payNow}`
      case RateEnum.flex:
        return `${freeCancelation}, ${payLater}`
      case RateEnum.save:
      default:
        return `${nonRefundable}, ${payNow}`
    }
  }
}

function getRoomCurrency(rate: SelectedRate | undefined) {
  if (!rate) {
    return null
  }

  if ("member" in rate && rate.member?.localPrice) {
    return rate.member.localPrice.currency
  }

  if ("public" in rate && rate.public?.localPrice) {
    return rate.public.localPrice.currency
  }
}
