import { cx } from "class-variance-authority"
import { useIntl } from "react-intl"

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

import { useIsLoggedIn } from "../../../../hooks/useIsLoggedIn"
import SignupPromoDesktop from "../../../SignupPromo/Desktop"
import { isSpecialRate } 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,
}: {
  selectedRates: ReturnType<typeof useSelectRateContext>["selectedRates"]
  isSubmitting: boolean
  input: ReturnType<typeof useSelectRateContext>["input"]
}) {
  const intl = useIntl()
  const isUserLoggedIn = useIsLoggedIn()

  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(
    {
      id: "booking.numberOfNights",
      defaultMessage: "{totalNights, plural, one {# night} other {# nights}}",
    },
    { totalNights: input.nights }
  )
  const totalAdults = intl.formatMessage(
    {
      id: "booking.numberOfAdults",
      defaultMessage: "{adults, plural, one {# adult} other {# adults}}",
    },
    {
      adults:
        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(
    {
      id: "booking.numberOfChildren",
      defaultMessage: "{children, plural, one {# child} other {# children}}",
    },
    {
      children: input.data?.booking.rooms.reduce(
        (acc, room) => acc + (room.childrenInRoom?.length ?? 0),
        0
      ),
    }
  )

  const totalChildren = childrenInOneOrMoreRooms ? `, ${childrenInroom}` : ""
  const totalRooms = intl.formatMessage(
    {
      id: "booking.numberOfRooms",
      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(isSpecialRate)

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

  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}>
          <Typography variant="Body/Paragraph/mdRegular">
            <p>
              {intl.formatMessage(
                {
                  id: "booking.totalPriceInclVat",
                  defaultMessage: "<b>Total price</b> (incl VAT)",
                },
                { b: (str) => <b>{str}</b> }
              )}
            </p>
          </Typography>
          <Typography
            variant="Body/Supporting text (caption)/smRegular"
            className={styles.secondaryText}
          >
            <p>{summaryPriceText}</p>
          </Typography>
        </div>
        <div className={styles.summaryPrice}>
          <div className={styles.summaryPriceTextDesktop}>
            <Typography
              variant="Title/Subtitle/md"
              className={cx(styles.alignRight, {
                [styles.red]: showDiscounted,
              })}
            >
              <p>
                {formatPrice(
                  intl,
                  selectedRates.totalPrice.local.price,
                  selectedRates.totalPrice.local.currency,
                  selectedRates.totalPrice.local.additionalPrice,
                  selectedRates.totalPrice.local.additionalPriceCurrency
                )}
              </p>
            </Typography>
            {showDiscounted && selectedRates.totalPrice.local.regularPrice && (
              <Typography
                variant="Body/Supporting text (caption)/smRegular"
                className={styles.regularPrice}
              >
                <p>
                  {formatPrice(
                    intl,
                    selectedRates.totalPrice.local.regularPrice,
                    selectedRates.totalPrice.local.currency
                  )}
                </p>
              </Typography>
            )}
            {!!selectedRates.totalPrice.requested && (
              <Typography
                variant="Body/Paragraph/mdRegular"
                className={styles.approxPrice}
              >
                <p>
                  {intl.formatMessage(
                    {
                      id: "booking.approxValue",
                      defaultMessage: "Approx. {value}",
                    },
                    {
                      value: formatPrice(
                        intl,
                        selectedRates.totalPrice.requested.price,
                        selectedRates.totalPrice.requested.currency,
                        selectedRates.totalPrice.requested.additionalPrice,
                        selectedRates.totalPrice.requested
                          .additionalPriceCurrency
                      ),
                    }
                  )}
                </p>
              </Typography>
            )}
          </div>
          <Button
            className={styles.continueButton}
            disabled={!isAllRoomsSelected || isSubmitting}
            theme="base"
            type="submit"
          >
            {intl.formatMessage({
              id: "common.continue",
              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}`}>
        <Typography
          variant="Title/Subtitle/md"
          className={styles.placeholderText}
        >
          <p>
            {intl.formatMessage(
              {
                id: "booking.roomIndex",
                defaultMessage: "Room {roomIndex}",
              },
              { roomIndex: roomIndex + 1 }
            )}
          </p>
        </Typography>
        <Typography
          variant="Body/Paragraph/mdRegular"
          className={styles.placeholderText}
        >
          <p>
            {intl.formatMessage({
              id: "booking.selectRoom",
              defaultMessage: "Select room",
            })}
          </p>
        </Typography>
      </div>
    )
  }

  return (
    <div key={roomIndex}>
      {isMultiRoom ? (
        <>
          <Typography variant="Title/Subtitle/md">
            <p>
              {intl.formatMessage(
                { id: "booking.roomIndex", defaultMessage: "Room {roomIndex}" },
                { roomIndex: roomIndex + 1 }
              )}
            </p>
          </Typography>
          <Typography variant="Body/Paragraph/mdRegular">
            <p>{room.roomInfo.roomType}</p>
          </Typography>
          <Typography
            variant="Body/Paragraph/mdRegular"
            className={styles.secondaryText}
          >
            <p>{getRateDetails(room.rate)}</p>
          </Typography>
        </>
      ) : (
        <>
          <Typography variant="Title/Subtitle/md">
            <p>{room.roomInfo.roomType}</p>
          </Typography>
          <Typography
            variant="Body/Paragraph/mdRegular"
            className={styles.secondaryText}
          >
            <p>{getRateDetails(room.rate)}</p>
          </Typography>
        </>
      )}
    </div>
  )
}

function useRateDetails() {
  const intl = useIntl()
  const freeCancelation = intl.formatMessage({
    id: "booking.freeCancellation",
    defaultMessage: "Free cancellation",
  })
  const nonRefundable = intl.formatMessage({
    id: "booking.nonRefundable",
    defaultMessage: "Non-refundable",
  })
  const freeBooking = intl.formatMessage({
    id: "booking.freeRebooking",
    defaultMessage: "Free rebooking",
  })
  const payLater = intl.formatMessage({
    id: "booking.payLater",
    defaultMessage: "Pay later",
  })
  const payNow = intl.formatMessage({
    id: "booking.payNow",
    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
  }
}
