import { useIntl } from "react-intl"

import { getRoomFeatureDescription } from "@scandic-hotels/booking-flow/utils/getRoomFeatureDescription"
import { sumPackages } from "@scandic-hotels/booking-flow/utils/SelectRate"
import { changeOrCancelDateFormat } from "@scandic-hotels/common/constants/dateFormats"
import { dt } from "@scandic-hotels/common/dt"
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
import Accordion from "@scandic-hotels/design-system/Accordion"
import AccordionItem from "@scandic-hotels/design-system/Accordion/AccordionItem"
import IconChip from "@scandic-hotels/design-system/IconChip"
import DiscountIcon from "@scandic-hotels/design-system/Icons/DiscountIcon"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import ImageGallery from "@scandic-hotels/design-system/ImageGallery"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"

import GuestDetails from "@/components/HotelReservation/MyStay/GuestDetails"
import PriceType from "@/components/HotelReservation/MyStay/PriceType"
import { hasModifiableRate } from "@/components/HotelReservation/MyStay/utils"
import useLang from "@/hooks/useLang"
import { mapApiImagesToGalleryImages } from "@/utils/imageGallery"

import RoomDetails from "./RoomDetails"

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

import type { BedTypeSchema } from "@scandic-hotels/booking-flow/stores/enter-details/types"
import type { BreakfastPackage } from "@scandic-hotels/trpc/routers/hotels/schemas/packages"
import type { BookingConfirmationSchema } from "@scandic-hotels/trpc/types/bookingConfirmation"
import type { Child } from "@scandic-hotels/trpc/types/child"
import type { Room as HotelRoom } from "@scandic-hotels/trpc/types/hotel"
import type { Packages } from "@scandic-hotels/trpc/types/packages"

import type { PriceTypeEnum } from "@/types/components/hotelReservation/myStay/myStay"
import type { SafeUser } from "@/types/user"

type PartialHotelRoom = Pick<
  HotelRoom,
  "descriptions" | "images" | "name" | "roomFacilities" | "roomTypes"
>

type Room = Pick<
  BookingConfirmationSchema,
  | "adults"
  | "bookingCode"
  | "cancellationNumber"
  | "checkInDate"
  | "cheques"
  | "confirmationNumber"
  | "refId"
  | "currencyCode"
  | "guest"
  | "rateDefinition"
  | "totalPoints"
  | "totalPrice"
  | "vouchers"
> & {
  bedType: BedTypeSchema
  breakfast: Omit<BreakfastPackage, "requestedPrice"> | false | undefined
  childrenInRoom: Child[]
  isCancelled: boolean
  packages: Packages | null
  priceType: PriceTypeEnum
  room: PartialHotelRoom | null
  roomName: string
  roomNumber: number
  terms: string | null
}

interface BookedRoomSidepeekContentProps {
  room: Room
  user: SafeUser
}

export default function BookedRoomSidePeekContent({
  room,
  user,
}: BookedRoomSidepeekContentProps) {
  const intl = useIntl()
  const lang = useLang()

  const {
    adults,
    bedType,
    bookingCode,
    breakfast,
    cancellationNumber,
    checkInDate,
    cheques,
    childrenInRoom,
    confirmationNumber,
    refId,
    currencyCode,
    guest,
    isCancelled,
    roomName,
    packages,
    priceType,
    rateDefinition,
    room: hotelRoom,
    roomNumber,
    totalPoints,
    terms,
    totalPrice,
    vouchers,
  } = room

  let totalRoomPrice = totalPrice
  // API returns negative values for totalPrice
  // on voucher bookings (╯°□°）╯︵ ┻━┻
  if (vouchers && totalRoomPrice < 0) {
    const pkgsSum = sumPackages(packages)
    totalRoomPrice = pkgsSum.price
  }

  const fromDate = dt(checkInDate).locale(lang)

  const galleryImages = hotelRoom
    ? mapApiImagesToGalleryImages(hotelRoom.images)
    : null

  const adultsMsg = intl.formatMessage(
    {
      id: "booking.numberOfAdults",
      defaultMessage: "{adults, plural, one {# adult} other {# adults}}",
    },
    {
      adults: adults,
    }
  )

  const childrenMsg = intl.formatMessage(
    {
      id: "booking.numberOfChildren",
      defaultMessage: "{children, plural, one {# child} other {# children}}",
    },
    {
      children: childrenInRoom.length,
    }
  )

  const adultsOnlyMsg = adultsMsg
  const adultsAndChildrenMsg = [adultsMsg, childrenMsg].join(", ")

  const formattedTotalPrice = formatPrice(intl, totalPrice, currencyCode)

  let breakfastPrice = intl.formatMessage({
    id: "common.noBreakfast",
    defaultMessage: "No breakfast",
  })
  if (rateDefinition.breakfastIncluded) {
    breakfastPrice = intl.formatMessage({
      id: "common.included",
      defaultMessage: "Included",
    })
  } else if (breakfast) {
    breakfastPrice = formatPrice(
      intl,
      breakfast.localPrice.totalPrice,
      breakfast.localPrice.currency
    )
  }

  const hotelRoomName = hotelRoom?.name || roomName

  return (
    <div className={styles.wrapper}>
      <div className={styles.roomHeader}>
        {isCancelled ? (
          <IconChip
            color={"red"}
            icon={
              <MaterialIcon
                icon="cancel"
                size={20}
                color="Icon/Feedback/Error"
              />
            }
          >
            <Typography variant="Body/Supporting text (caption)/smBold">
              <span>
                {intl.formatMessage({
                  id: "common.cancelled",
                  defaultMessage: "Cancelled",
                })}
              </span>
            </Typography>
          </IconChip>
        ) : (
          <div className={styles.chip}>
            <Typography variant="Tag/sm">
              <span>
                {intl.formatMessage(
                  {
                    id: "booking.roomIndex",
                    defaultMessage: "Room {roomIndex}",
                  },
                  { roomIndex: roomNumber }
                )}
              </span>
            </Typography>
          </div>
        )}
        <div className={styles.reference}>
          <Typography variant="Body/Supporting text (caption)/smBold">
            {isCancelled ? (
              <span>
                {intl.formatMessage({
                  id: "booking.cancellationNo",
                  defaultMessage: "Cancellation no",
                })}
                {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
                {":"}
              </span>
            ) : (
              <span>
                {intl.formatMessage({
                  id: "common.bookingNumber",
                  defaultMessage: "Booking number",
                })}
                {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
                {":"}
              </span>
            )}
          </Typography>
          <Typography variant="Body/Supporting text (caption)/smRegular">
            {isCancelled ? (
              <span className={styles.cancellationNumber}>
                {cancellationNumber}
              </span>
            ) : (
              <span>{confirmationNumber}</span>
            )}
          </Typography>
        </div>
      </div>
      <div className={styles.mainContent}>
        <div className={styles.imageContainer}>
          {galleryImages ? (
            <ImageGallery
              height={280}
              images={galleryImages}
              title={hotelRoomName}
            />
          ) : null}
        </div>
        <div className={styles.roomDetails}>
          <div className={styles.row}>
            <span className={styles.rowTitle}>
              <MaterialIcon icon="person" color="Icon/Default" size={20} />
              <Typography variant="Body/Paragraph/mdBold">
                <p>
                  {intl.formatMessage({
                    id: "booking.guests",
                    defaultMessage: "Guests",
                  })}
                </p>
              </Typography>
            </span>
            <div className={styles.rowContent}>
              <Typography variant="Body/Paragraph/mdRegular">
                <p>
                  {childrenInRoom.length > 0
                    ? adultsAndChildrenMsg
                    : adultsOnlyMsg}
                </p>
              </Typography>
            </div>
          </div>
          <div className={styles.row}>
            <span className={styles.rowTitle}>
              <MaterialIcon icon="contract" color="Icon/Default" size={20} />
              <Typography variant="Body/Paragraph/mdBold">
                <p>
                  {intl.formatMessage({
                    id: "booking.terms",
                    defaultMessage: "Terms",
                  })}
                </p>
              </Typography>
            </span>
            <div className={styles.rowContent}>
              <Typography variant="Body/Paragraph/mdRegular">
                <p>{terms}</p>
              </Typography>
            </div>
          </div>
          {hasModifiableRate(rateDefinition.cancellationRule) && (
            <div className={styles.row}>
              <span className={styles.rowTitle}>
                <MaterialIcon icon="refresh" color="Icon/Default" size={20} />
                <Typography variant="Body/Paragraph/mdBold">
                  <p>
                    {intl.formatMessage({
                      id: "myStay.modifyBy",
                      defaultMessage: "Modify by",
                    })}
                  </p>
                </Typography>
              </span>
              <div className={styles.rowContent}>
                <Typography variant="Body/Paragraph/mdRegular">
                  <p>
                    {intl.formatMessage(
                      {
                        id: "common.untilWithTimeAndDate",
                        defaultMessage: "Until {time}, {date}",
                      },
                      {
                        time: "18:00",
                        date: fromDate.format(changeOrCancelDateFormat[lang]),
                      }
                    )}
                  </p>
                </Typography>
              </div>
            </div>
          )}
          <div className={styles.row}>
            <span className={styles.rowTitle}>
              <MaterialIcon icon="coffee" color="Icon/Default" size={20} />
              <Typography variant="Body/Paragraph/mdBold">
                <p>
                  {intl.formatMessage({
                    id: "common.breakfast",
                    defaultMessage: "Breakfast",
                  })}
                </p>
              </Typography>
            </span>
            <div className={styles.rowContent}>
              <Typography variant="Body/Paragraph/mdRegular">
                <p>{breakfastPrice}</p>
              </Typography>
            </div>
          </div>
          {packages?.some((item) =>
            Object.values(RoomPackageCodeEnum).includes(
              item.code as RoomPackageCodeEnum
            )
          ) && (
            <div className={styles.row}>
              <span className={styles.rowTitle}>
                <MaterialIcon
                  icon="meeting_room"
                  color="Icon/Default"
                  size={20}
                />
                <Typography variant="Body/Paragraph/mdBold">
                  <p>
                    {intl.formatMessage({
                      id: "booking.roomClassification",
                      defaultMessage: "Room classification",
                    })}
                  </p>
                </Typography>
              </span>
              <div className={styles.rowContent}>
                <Typography variant="Body/Paragraph/mdRegular">
                  <p>
                    {packages
                      ?.filter((item) =>
                        Object.values(RoomPackageCodeEnum).includes(
                          item.code as RoomPackageCodeEnum
                        )
                      )
                      .map((item) =>
                        getRoomFeatureDescription(
                          item.code,
                          item.description,
                          intl
                        )
                      )
                      .join(", ")}
                  </p>
                </Typography>
              </div>
            </div>
          )}
          <div className={styles.row}>
            <span className={styles.rowTitle}>
              <MaterialIcon icon="bed" color="Icon/Default" size={20} />
              <Typography variant="Body/Paragraph/mdBold">
                <p>
                  {intl.formatMessage({
                    id: "booking.bedPreference",
                    defaultMessage: "Bed preference",
                  })}
                </p>
              </Typography>
            </span>
            <div className={styles.rowContent}>
              <Typography variant="Body/Paragraph/mdRegular">
                <p>{bedType?.description}</p>
              </Typography>
            </div>
          </div>
        </div>
        <div className={styles.bookingInformation}>
          <div className={styles.priceDetails}>
            <div className={styles.price}>
              <Typography variant="Body/Lead text">
                <p>
                  {intl.formatMessage({
                    id: "booking.roomTotal",
                    defaultMessage: "Room total",
                  })}
                </p>
              </Typography>

              <PriceType
                cheques={cheques}
                formattedTotalPrice={formattedTotalPrice}
                isCancelled={isCancelled}
                priceType={priceType}
                currencyCode={currencyCode}
                rateDefinition={rateDefinition}
                totalPoints={totalPoints}
                totalPrice={totalRoomPrice}
                vouchers={vouchers}
              />
            </div>
          </div>
        </div>
        {bookingCode && (
          <Typography variant="Body/Supporting text (caption)/smBold">
            <IconChip
              color="blue"
              icon={<DiscountIcon color="Icon/Feedback/Information" />}
            >
              {intl.formatMessage(
                {
                  id: "booking.bookingCodeWithValue",
                  defaultMessage: "<strong>Booking code</strong>: {value}",
                },
                {
                  value: bookingCode,
                  strong: (text) => (
                    <Typography variant="Body/Supporting text (caption)/smBold">
                      <strong>{text}</strong>
                    </Typography>
                  ),
                }
              )}
            </IconChip>
          </Typography>
        )}

        <GuestDetails
          refId={refId}
          guest={guest}
          isCancelled={isCancelled}
          user={user}
        />
      </div>
      {hotelRoom ? (
        <Accordion type="sidepeek">
          <AccordionItem
            title={intl.formatMessage({
              id: "sidepeek.roomDetails",
              defaultMessage: "Room details",
            })}
            type="sidepeek"
          >
            <RoomDetails
              roomDescription={hotelRoom.descriptions.medium}
              roomFacilities={hotelRoom.roomFacilities}
              roomTypes={hotelRoom.roomTypes}
            />
          </AccordionItem>
        </Accordion>
      ) : null}
    </div>
  )
}
