import { describe, expect, test } from "@jest/globals"
import { act, cleanup, render, screen, within } from "@testing-library/react"
import { type IntlConfig, IntlProvider } from "react-intl"

import { Lang } from "@/constants/languages"

import {
  bedType,
  booking,
  breakfastPackage,
  guestDetailsMember,
  guestDetailsNonMember,
  roomPrice,
  roomRate,
} from "@/__mocks__/hotelReservation"
import { initIntl } from "@/i18n"

import SummaryUI from "./UI"

import type { PropsWithChildren } from "react"

import { ChildBedMapEnum } from "@/types/components/bookingWidget/enums"

jest.mock("@/lib/api", () => ({
  fetchRetry: jest.fn((fn) => fn),
}))

function createWrapper(intlConfig: IntlConfig) {
  return function Wrapper({ children }: PropsWithChildren) {
    return (
      <IntlProvider
        messages={intlConfig.messages}
        locale={intlConfig.locale}
        defaultLocale={intlConfig.defaultLocale}
      >
        {children}
      </IntlProvider>
    )
  }
}

// TODO: add type definition to this object
export const rooms = [
  {
    adults: 2,
    childrenInRoom: [{ bed: ChildBedMapEnum.IN_EXTRA_BED, age: 5 }],
    bedType: {
      description: bedType.queen.description,
      roomTypeCode: bedType.queen.value,
    },
    breakfast: breakfastPackage,
    guest: guestDetailsNonMember,
    roomRate: roomRate,
    roomPrice: roomPrice,
    roomType: "Standard",
    rateDetails: [],
    cancellationText: "Non-refundable",
  },
  {
    adults: 1,
    childrenInRoom: [],
    bedType: {
      description: bedType.king.description,
      roomTypeCode: bedType.king.value,
    },
    breakfast: undefined,
    guest: guestDetailsMember,
    roomRate: roomRate,
    roomPrice: roomPrice,
    roomType: "Standard",
    rateDetails: [],
    cancellationText: "Non-refundable",
  },
]

describe("EnterDetails Summary", () => {
  afterEach(() => {
    cleanup()
  })

  test("render with single room correctly", async () => {
    const intl = await initIntl(Lang.en)

    await act(async () => {
      render(
        <SummaryUI
          booking={booking}
          rooms={rooms.slice(0, 1)}
          isMember={false}
          breakfastIncluded={false}
          packages={[]}
          totalPrice={{
            requested: {
              currency: "EUR",
              price: 133,
            },
            local: {
              currency: "SEK",
              price: 1500,
            },
          }}
          vat={12}
          toggleSummaryOpen={jest.fn()}
          togglePriceDetailsModalOpen={jest.fn()}
        />,
        {
          wrapper: createWrapper(intl),
        }
      )
    })

    screen.getByText("2 adults, 1 child")
    screen.getByText("Standard")
    screen.getByText("1,525 SEK")
    screen.getByText(bedType.queen.description)
    screen.getByText("Breakfast buffet")
    screen.getByText("1,500 SEK")
    screen.getByTestId("signup-promo-desktop")
  })

  test("render with multiple rooms correctly", async () => {
    const intl = await initIntl(Lang.en)

    await act(async () => {
      render(
        <SummaryUI
          booking={booking}
          rooms={rooms}
          isMember={false}
          breakfastIncluded={false}
          packages={[]}
          totalPrice={{
            requested: {
              currency: "EUR",
              price: 133,
            },
            local: {
              currency: "SEK",
              price: 1500,
            },
          }}
          vat={12}
          toggleSummaryOpen={jest.fn()}
          togglePriceDetailsModalOpen={jest.fn()}
        />,
        {
          wrapper: createWrapper(intl),
        }
      )
    })

    const room1 = within(screen.getByTestId("summary-room-1"))
    room1.getByText("Standard")
    room1.getByText("2 adults, 1 child")
    room1.getByText(bedType.queen.description)
    room1.getByText("Breakfast buffet")

    const room2 = within(screen.getByTestId("summary-room-2"))
    room2.getByText("Standard")
    room2.getByText("1 adult")
    const room2Breakfast = room2.queryByText("Breakfast buffet")
    expect(room2Breakfast).not.toBeInTheDocument()

    room2.getByText(bedType.king.description)
  })
})
