"use client"

import { Fragment } from "react"
import { useIntl } from "react-intl"

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

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

import Body from "@/components/TempDesignSystem/Text/Body"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import useLang from "@/hooks/useLang"
import { formatPrice } from "@/utils/numberFormatting"

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

import type { Price } from "@/types/components/hotelReservation/price"
import { CurrencyEnum } from "@/types/enums/currency"
import type { RoomState } from "@/types/stores/enter-details"

function Row({
  label,
  value,
  bold,
}: {
  label: string
  value: string
  bold?: boolean
}) {
  return (
    <tr className={styles.row}>
      <td>
        <Caption type={bold ? "bold" : undefined}>{label}</Caption>
      </td>
      <td className={styles.price}>
        <Caption type={bold ? "bold" : undefined}>{value}</Caption>
      </td>
    </tr>
  )
}

function TableSection({ children }: React.PropsWithChildren) {
  return <tbody className={styles.tableSection}>{children}</tbody>
}

function TableSectionHeader({
  title,
  subtitle,
}: {
  title: string
  subtitle?: string
}) {
  return (
    <tr>
      <th colSpan={2}>
        <Body>{title}</Body>
        {subtitle ? <Body>{subtitle}</Body> : null}
      </th>
    </tr>
  )
}

export type Room = Pick<
  RoomState["room"],
  | "adults"
  | "bedType"
  | "breakfast"
  | "childrenInRoom"
  | "roomFeatures"
  | "roomRate"
  | "roomType"
> & {
  guest?: RoomState["room"]["guest"]
}

export interface PriceDetailsTableProps {
  bookingCode?: string
  fromDate: string
  isMember: boolean
  rooms: Room[]
  toDate: string
  totalPrice: Price
  vat: number
}

export default function PriceDetailsTable({
  bookingCode,
  fromDate,
  isMember,
  rooms,
  toDate,
  totalPrice,
  vat,
}: PriceDetailsTableProps) {
  const intl = useIntl()
  const lang = useLang()

  const diff = dt(toDate).diff(fromDate, "days")
  const nights = intl.formatMessage(
    { id: "{totalNights, plural, one {# night} other {# nights}}" },
    { totalNights: diff }
  )
  const vatPercentage = vat / 100
  const vatAmount = totalPrice.local.price * vatPercentage

  const priceExclVat = totalPrice.local.price - vatAmount

  const duration = ` ${dt(fromDate).locale(lang).format("ddd, D MMM")}
          -
          ${dt(toDate).locale(lang).format("ddd, D MMM")} (${nights})`
  const noVatCurrencies = [
    CurrencyEnum.CC,
    CurrencyEnum.POINTS,
    CurrencyEnum.Voucher,
  ]
  return (
    <table className={styles.priceDetailsTable}>
      {rooms.map((room, idx) => {
        const isMainRoom = idx === 0
        const getMemberRate =
          room.guest?.join ||
          room.guest?.membershipNo ||
          (isMainRoom && isMember)

        let price
        if (
          getMemberRate &&
          "member" in room.roomRate &&
          room.roomRate.member
        ) {
          price = room.roomRate.member
        } else if ("public" in room.roomRate && room.roomRate.public) {
          price = room.roomRate.public
        }
        const voucherPrice =
          "voucher" in room.roomRate ? room.roomRate.voucher : undefined
        const chequePrice =
          "corporateCheque" in room.roomRate
            ? room.roomRate.corporateCheque
            : undefined
        const redemptionPrice = "redemption" in room.roomRate ? room.roomRate.redemption : undefined
        if (!price && !voucherPrice && !chequePrice && !redemptionPrice) {
          return null
        }
        return (
          <Fragment key={idx}>
            <TableSection>
              {rooms.length > 1 && (
                <Body textTransform="bold">
                  {intl.formatMessage({ id: "Room" })} {idx + 1}
                </Body>
              )}
              <TableSectionHeader title={room.roomType} subtitle={duration} />
              {price && (
                <>
                  <Row
                    label={intl.formatMessage({
                      id: "Average price per night",
                    })}
                    value={formatPrice(
                      intl,
                      price.localPrice.pricePerNight,
                      price.localPrice.currency
                    )}
                  />
                  {room.roomFeatures
                    ? room.roomFeatures.map((feature) => (
                        <Row
                          key={feature.code}
                          label={feature.description}
                          value={formatPrice(
                            intl,
                            +feature.localPrice.totalPrice,
                            feature.localPrice.currency
                          )}
                        />
                      ))
                    : null}
                  {room.bedType ? (
                    <Row
                      label={room.bedType.description}
                      value={formatPrice(intl, 0, price.localPrice.currency)}
                    />
                  ) : null}
                  <Row
                    bold
                    label={intl.formatMessage({ id: "Room charge" })}
                    value={formatPrice(
                      intl,
                      price.localPrice.pricePerStay,
                      price.localPrice.currency
                    )}
                  />
                </>
              )}
              {voucherPrice && (
                <Row
                  bold
                  label={intl.formatMessage({ id: "Room charge" })}
                  value={formatPrice(
                    intl,
                    voucherPrice.numberOfVouchers,
                    CurrencyEnum.Voucher
                  )}
                />
              )}
              {chequePrice && (
                <Row
                  bold
                  label={intl.formatMessage({ id: "Room charge" })}
                  value={formatPrice(
                    intl,
                    chequePrice.localPrice.numberOfCheques,
                    CurrencyEnum.CC,
                    chequePrice.localPrice.additionalPricePerStay,
                    chequePrice.localPrice.currency ?? undefined
                  )}
                />
              )}
              {redemptionPrice && (
                <Row
                  bold
                  label={intl.formatMessage({ id: "Room charge" })}
                  value={formatPrice(
                    intl,
                    redemptionPrice.localPrice.pointsPerStay,
                    CurrencyEnum.POINTS,
                    redemptionPrice.localPrice.additionalPricePerStay,
                    redemptionPrice.localPrice.currency ?? undefined
                  )}
                />
              )}
            </TableSection>

            {room.breakfast ? (
              <TableSection>
                <Row
                  label={intl.formatMessage(
                    {
                      id: "Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}",
                    },
                    { totalAdults: room.adults, totalBreakfasts: diff }
                  )}
                  value={formatPrice(
                    intl,
                    room.breakfast.localPrice.price * room.adults,
                    room.breakfast.localPrice.currency
                  )}
                />
                {room.childrenInRoom?.length ? (
                  <Row
                    label={intl.formatMessage(
                      {
                        id: "Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}",
                      },
                      {
                        totalChildren: room.childrenInRoom.length,
                        totalBreakfasts: diff,
                      }
                    )}
                    value={formatPrice(
                      intl,
                      0,
                      room.breakfast.localPrice.currency
                    )}
                  />
                ) : null}
                <Row
                  bold
                  label={intl.formatMessage({
                    id: "Breakfast charge",
                  })}
                  value={formatPrice(
                    intl,
                    room.breakfast.localPrice.price * room.adults * diff,
                    room.breakfast.localPrice.currency
                  )}
                />
              </TableSection>
            ) : null}
          </Fragment>
        )
      })}
      <TableSection>
        <TableSectionHeader title={intl.formatMessage({ id: "Total" })} />
        {
          // @ts-expect-error Currency type is string instead of CurrencyEnum. Change also impacts packages
          !noVatCurrencies.includes(totalPrice.local.currency) ? (
            <>
              <Row
                label={intl.formatMessage({ id: "Price excluding VAT" })}
                value={formatPrice(
                  intl,
                  priceExclVat,
                  totalPrice.local.currency
                )}
              />
              <Row
                label={intl.formatMessage({ id: "VAT {vat}%" }, { vat })}
                value={formatPrice(intl, vatAmount, totalPrice.local.currency)}
              />
            </>
          ) : null
        }
        <tr className={styles.row}>
          <td>
            <Body textTransform="bold">
              {intl.formatMessage({ id: "Price including VAT" })}
            </Body>
          </td>
          <td className={styles.price}>
            <Body textTransform="bold">
              {formatPrice(
                intl,
                totalPrice.local.price,
                totalPrice.local.currency,
                totalPrice.local.additionalPrice,
                totalPrice.local.additionalPriceCurrency
              )}
            </Body>
          </td>
        </tr>
        {totalPrice.local.regularPrice ? (
          <tr className={styles.row}>
            <td></td>
            <td className={styles.price}>
              <Caption color="uiTextMediumContrast" striked={true}>
                {formatPrice(
                  intl,
                  totalPrice.local.regularPrice,
                  totalPrice.local.currency
                )}
              </Caption>
            </td>
          </tr>
        ) : null}
        {bookingCode && totalPrice.local.regularPrice && (
          <tr className={styles.row}>
            <td>
              <MaterialIcon icon="sell" />
              {bookingCode}
            </td>
            <td></td>
          </tr>
        )}
      </TableSection>
    </table>
  )
}
