import { useIntl } from "react-intl"

import DiscountIcon from "@scandic-hotels/design-system/Icons/DiscountIcon"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"

import { dt } from "@/lib/dt"

import GuestDetails from "@/components/HotelReservation/MyStay/GuestDetails"
import PriceType from "@/components/HotelReservation/MyStay/PriceType"
import { hasModifiableRate } from "@/components/HotelReservation/MyStay/utils"
import { sumPackages } from "@/components/HotelReservation/utils"
import ImageGallery from "@/components/ImageGallery"
import Accordion from "@/components/TempDesignSystem/Accordion"
import AccordionItem from "@/components/TempDesignSystem/Accordion/AccordionItem"
import IconChip from "@/components/TempDesignSystem/IconChip"
import SidePeekSelfControlled from "@/components/TempDesignSystem/SidePeekSelfControlled"
import useLang from "@/hooks/useLang"
import { mapApiImagesToGalleryImages } from "@/utils/imageGallery"
import { formatPrice } from "@/utils/numberFormatting"

import RoomDetails from "./RoomDetails"

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

import type { BreakfastPackage } from "@/types/components/hotelReservation/breakfast"
import type { BedTypeSchema } from "@/types/components/hotelReservation/enterDetails/bedType"
import type { PriceTypeEnum } from "@/types/components/hotelReservation/myStay/myStay"
import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
import type { Child } from "@/types/components/hotelReservation/selectRate/selectRate"
import type { Room as HotelRoom } from "@/types/hotel"
import type { Packages } from "@/types/requests/packages"
import type { BookingConfirmationSchema } from "@/types/trpc/routers/booking/confirmation"
import type { SafeUser } from "@/types/user"

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

export 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
  roomName: string
  roomNumber: number
  terms: string | null
}

interface RoomDetailsSidePeekProps {
  hotelRoom: PartialHotelRoom | null
  room: Room
  user: SafeUser
}

export default function BookedRoomSidePeek({
  hotelRoom,
  room,
  user,
}: RoomDetailsSidePeekProps) {
  const intl = useIntl()
  const lang = useLang()

  const {
    adults,
    bedType,
    bookingCode,
    breakfast,
    cancellationNumber,
    checkInDate,
    cheques,
    childrenInRoom,
    confirmationNumber,
    refId,
    currencyCode,
    guest,
    isCancelled,
    roomName,
    packages,
    priceType,
    rateDefinition,
    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(
    {
      defaultMessage: "{adults, plural, one {# adult} other {# adults}}",
    },
    {
      adults: adults,
    }
  )

  const childrenMsg = intl.formatMessage(
    {
      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({
    defaultMessage: "No breakfast",
  })
  if (rateDefinition.breakfastIncluded) {
    breakfastPrice = intl.formatMessage({
      defaultMessage: "Included",
    })
  } else if (breakfast) {
    breakfastPrice = formatPrice(
      intl,
      breakfast.localPrice.totalPrice,
      breakfast.localPrice.currency
    )
  }

  const hotelRoomName = hotelRoom?.name || roomName

  return (
    <SidePeekSelfControlled title={hotelRoomName}>
      <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({
                    defaultMessage: "Cancelled",
                  })}
                </span>
              </Typography>
            </IconChip>
          ) : (
            <div className={styles.chip}>
              <Typography variant="Tag/sm">
                <span>
                  {intl.formatMessage(
                    {
                      defaultMessage: "Room {roomIndex}",
                    },
                    { roomIndex: roomNumber }
                  )}
                </span>
              </Typography>
            </div>
          )}
          <div className={styles.reference}>
            <Typography variant="Body/Supporting text (caption)/smBold">
              {isCancelled ? (
                <span>
                  {intl.formatMessage({
                    defaultMessage: "Cancellation no",
                  })}
                  {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
                  {":"}
                </span>
              ) : (
                <span>
                  {intl.formatMessage({
                    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({
                      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({
                      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({
                        defaultMessage: "Modify By",
                      })}
                    </p>
                  </Typography>
                </span>
                <div className={styles.rowContent}>
                  <Typography variant="Body/Paragraph/mdRegular">
                    <p>
                      {intl.formatMessage(
                        {
                          defaultMessage: "Until {time}, {date}",
                        },
                        { time: "18:00", date: fromDate.format("dddd D MMM") }
                      )}
                    </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({
                      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({
                        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) => item.description)
                        .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({
                      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({
                      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(
                  {
                    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>
            <AccordionItem
              title={intl.formatMessage({
                defaultMessage: "Room details",
              })}
              variant="sidepeek"
            >
              <RoomDetails
                roomDescription={hotelRoom.descriptions.medium}
                roomFacilities={hotelRoom.roomFacilities}
                roomTypes={hotelRoom.roomTypes}
              />
            </AccordionItem>
          </Accordion>
        ) : null}
      </div>
    </SidePeekSelfControlled>
  )
}
