// import { describe, expect, test } from "@jest/globals"
// import { act, renderHook, waitFor } from "@testing-library/react"
// import { type PropsWithChildren } from "react"

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

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

// import { detailsStorageName, useEnterDetailsStore } from "."

// import type { BedTypeSelection } from "@/types/components/hotelReservation/enterDetails/bedType"
// import type { BreakfastPackages } from "@/types/components/hotelReservation/enterDetails/breakfast"
// import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
// import { PackageTypeEnum } from "@/types/enums/packages"
// import { StepEnum } from "@/types/enums/step"
// import type { PersistedState } from "@/types/stores/enter-details"

// jest.mock("react", () => ({
//   ...jest.requireActual("react"),
//   cache: jest.fn(),
// }))

// jest.mock("@/server/utils", () => ({
//   toLang: () => Lang.en,
// }))

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

// interface CreateWrapperParams {
//   bedTypes?: BedTypeSelection[]
//   bookingParams?: SelectRateSearchParams
//   breakfastIncluded?: boolean
//   breakfastPackages?: BreakfastPackages | null
//   mustBeGuaranteed?: boolean
// }

// function createWrapper(params: Partial<CreateWrapperParams> = {}) {
//   const {
//     breakfastIncluded = false,
//     breakfastPackages = null,
//     mustBeGuaranteed = false,
//     bookingParams = booking,
//     bedTypes = [bedType.king, bedType.queen],
//   } = params

//   return function Wrapper({ children }: PropsWithChildren) {
//     return (
//       <EnterDetailsProvider
//         booking={bookingParams}
//         breakfastPackages={breakfastPackages}
//         rooms={[
//           {
//             bedTypes,
//             packages: null,
//             mustBeGuaranteed,
//             breakfastIncluded,
//             cancellationText: "",
//             rateDetails: [],
//             roomType: "Standard",
//             roomTypeCode: "QS",
//             roomRate: roomRate,
//           },
//           {
//             bedTypes,
//             packages: null,
//             mustBeGuaranteed,
//             breakfastIncluded,
//             cancellationText: "",
//             rateDetails: [],
//             roomType: "Standard",
//             roomTypeCode: "QS",
//             roomRate: roomRate,
//           },
//         ]}
//         searchParamsStr=""
//         user={null}
//         vat={0}
//       >
//         {children}
//       </EnterDetailsProvider>
//     )
//   }
// }

// describe("Enter Details Store", () => {
//   beforeEach(() => {
//     window.sessionStorage.clear()
//   })

//   describe("initial state", () => {
//     test("initialize with correct default values", () => {
//       const { result } = renderHook(
//         () => useEnterDetailsStore((state) => state),
//         {
//           wrapper: createWrapper(),
//         }
//       )
//       const state = result.current

//       expect(state.booking).toEqual(booking)

//       // room 1
//       const room1 = result.current.rooms[0]

//       expect(room1.currentStep).toBe(StepEnum.selectBed)

//       expect(room1.room.roomPrice.perNight.local.price).toEqual(
//         roomRate.publicRate.localPrice.pricePerNight
//       )
//       expect(room1.room.bedType).toEqual(undefined)
//       expect(Object.values(room1.room.guest).every((value) => value === ""))

//       // room 2
//       const room2 = result.current.rooms[1]

//       expect(room2.currentStep).toBe(null)
//       expect(room2.room.roomPrice.perNight.local.price).toEqual(
//         room2.room.roomRate.publicRate.localPrice.pricePerNight
//       )
//       expect(room2.room.bedType).toEqual(undefined)
//       expect(Object.values(room2.room.guest).every((value) => value === ""))
//     })

//     test("initialize with correct values from session storage", () => {
//       const storage: PersistedState = {
//         activeRoom: 0,
//         booking: booking,
//         rooms: [
//           {
//             currentStep: StepEnum.selectBed,
//             isComplete: false,
//             room: {
//               adults: 1,
//               bedType: {
//                 description: bedType.king.description,
//                 roomTypeCode: bedType.king.value,
//               },
//               bedTypes: [
//                 {
//                   description: bedType.king.description,
//                   extraBed: undefined,
//                   size: {
//                     min: 100,
//                     max: 120,
//                   },
//                   type: BedTypeEnum.King,
//                   value: bedType.king.value,
//                 },
//               ],
//               breakfastIncluded: false,
//               breakfast: breakfastPackage,
//               cancellationText: "Non-refundable",
//               childrenInRoom: [],
//               guest: guestDetailsNonMember,
//               rateDetails: [],
//               roomFeatures: null,
//               roomPrice: roomPrice,
//               roomRate: roomRate,
//               roomType: "Classic Double",
//               roomTypeCode: "QS",
//             },
//             steps: {
//               [StepEnum.selectBed]: {
//                 step: StepEnum.selectBed,
//                 isValid: true,
//               },
//               [StepEnum.breakfast]: {
//                 step: StepEnum.breakfast,
//                 isValid: true,
//               },
//               [StepEnum.details]: {
//                 step: StepEnum.details,
//                 isValid: true,
//               },
//             },
//           },
//         ],
//       }

//       window.sessionStorage.setItem(detailsStorageName, JSON.stringify(storage))

//       const { result } = renderHook(
//         () => useEnterDetailsStore((state) => state),
//         {
//           wrapper: createWrapper(),
//         }
//       )

//       expect(result.current.booking).toEqual(storage.booking)
//       expect(result.current.rooms[0]).toEqual(storage.rooms[0])
//     })
//   })

//   test("add bedtype and proceed to next step", async () => {
//     const { result } = renderHook(
//       () => useEnterDetailsStore((state) => state),
//       {
//         wrapper: createWrapper(),
//       }
//     )

//     let room1 = result.current.rooms[0]
//     expect(room1.currentStep).toEqual(StepEnum.selectBed)

//     const selectedBedType = {
//       roomTypeCode: bedType.king.value,
//       description: bedType.king.description,
//     }

//     await act(async () => {
//       result.current.actions.updateBedType(0)(selectedBedType)
//     })

//     room1 = result.current.rooms[0]

//     expect(room1.steps[StepEnum.selectBed].isValid).toEqual(true)
//     expect(room1.room.bedType).toEqual(selectedBedType)

//     expect(room1.currentStep).toEqual(StepEnum.breakfast)
//   })

//   test("complete step and navigate to next step", async () => {
//     const { result } = renderHook(
//       () => useEnterDetailsStore((state) => state),
//       {
//         wrapper: createWrapper(),
//       }
//     )

//     // Room 1
//     expect(result.current.activeRoom).toEqual(0)

//     let room1 = result.current.rooms[0]
//     expect(room1.currentStep).toEqual(StepEnum.selectBed)

//     await act(async () => {
//       result.current.actions.updateBedType(0)({
//         roomTypeCode: bedType.king.value,
//         description: bedType.king.description,
//       })
//     })

//     room1 = result.current.rooms[0]
//     expect(room1.steps[StepEnum.selectBed].isValid).toEqual(true)
//     expect(room1.currentStep).toEqual(StepEnum.breakfast)

//     await act(async () => {
//       result.current.actions.updateBreakfast(0)(breakfastPackage)
//     })

//     room1 = result.current.rooms[0]
//     expect(room1.steps[StepEnum.breakfast]?.isValid).toEqual(true)
//     expect(room1.currentStep).toEqual(StepEnum.details)

//     await act(async () => {
//       result.current.actions.updateDetails(0)(guestDetailsNonMember)
//     })

//     expect(result.current.canProceedToPayment).toBe(false)

//     // Room 2
//     expect(result.current.activeRoom).toEqual(1)

//     let room2 = result.current.rooms[1]
//     expect(room2.currentStep).toEqual(StepEnum.selectBed)

//     await act(async () => {
//       const selectedBedType = {
//         roomTypeCode: bedType.king.value,
//         description: bedType.king.description,
//       }
//       result.current.actions.updateBedType(1)(selectedBedType)
//     })

//     room2 = result.current.rooms[1]
//     expect(room2.steps[StepEnum.selectBed].isValid).toEqual(true)
//     expect(room2.currentStep).toEqual(StepEnum.breakfast)

//     await act(async () => {
//       result.current.actions.updateBreakfast(1)(breakfastPackage)
//     })

//     room2 = result.current.rooms[1]
//     expect(room2.steps[StepEnum.breakfast]?.isValid).toEqual(true)
//     expect(room2.currentStep).toEqual(StepEnum.details)

//     await act(async () => {
//       result.current.actions.updateDetails(1)(guestDetailsNonMember)
//     })

//     expect(result.current.canProceedToPayment).toBe(true)
//   })

//   test("all steps needs to be completed before going to next room", async () => {
//     const { result } = renderHook(
//       () => useEnterDetailsStore((state) => state),
//       {
//         wrapper: createWrapper(),
//       }
//     )

//     await act(async () => {
//       result.current.actions.updateDetails(0)(guestDetailsNonMember)
//     })

//     expect(result.current.activeRoom).toEqual(1)

//     await act(async () => {
//       result.current.actions.setStep(StepEnum.breakfast)
//     })

//     expect(result.current.activeRoom).toEqual(1)
//   })

//   test("can go back and modify room 1 after completion", async () => {
//     const { result } = renderHook(
//       () => useEnterDetailsStore((state) => state),
//       {
//         wrapper: createWrapper(),
//       }
//     )

//     await act(async () => {
//       result.current.actions.updateBedType(0)({
//         roomTypeCode: bedType.king.value,
//         description: bedType.king.description,
//       })
//       result.current.actions.updateBreakfast(0)(breakfastPackage)
//       result.current.actions.updateDetails(0)(guestDetailsNonMember)
//     })

//     // now we are at room 2
//     expect(result.current.activeRoom).toEqual(1)

//     await act(async () => {
//       result.current.actions.setStep(StepEnum.breakfast) // click "modify"
//     })

//     expect(result.current.activeRoom).toEqual(1)

//     await act(async () => {
//       result.current.actions.updateBreakfast(1)(breakfastPackage)
//     })

//     // going back to room 2
//     expect(result.current.activeRoom).toEqual(1)
//   })

//   test("breakfast step should be hidden when breakfast is included", async () => {
//     const { result } = renderHook(
//       () => useEnterDetailsStore((state) => state),
//       {
//         wrapper: createWrapper({ breakfastPackages: null }),
//       }
//     )

//     const room1 = result.current.rooms[0]
//     expect(Object.keys(room1.steps)).not.toContain(StepEnum.breakfast)

//     const room2 = result.current.rooms[1]
//     expect(Object.keys(room2.steps)).not.toContain(StepEnum.breakfast)
//   })

//   test("select bed step should be skipped when there is only one bedtype", async () => {
//     const { result } = renderHook(
//       () => useEnterDetailsStore((state) => state),
//       {
//         wrapper: createWrapper({
//           bedTypes: [bedType.queen],
//           breakfastPackages: [
//             {
//               code: "TEST",
//               description: "Description",
//               localPrice: {
//                 currency: "SEK",
//                 price: "100",
//                 totalPrice: "100",
//               },
//               requestedPrice: {
//                 currency: "SEK",
//                 price: "100",
//                 totalPrice: "100",
//               },
//               packageType: PackageTypeEnum.BreakfastAdult,
//             },
//           ],
//         }),
//       }
//     )

//     const room1 = result.current.rooms[0]
//     expect(room1.steps[StepEnum.selectBed].isValid).toEqual(true)
//     expect(room1.currentStep).toEqual(StepEnum.breakfast)

//     const room2 = result.current.rooms[1]
//     expect(room2.steps[StepEnum.selectBed].isValid).toEqual(true)
//     expect(room2.currentStep).toEqual(null)
//   })

//   describe("price calculation", () => {
//     test("total price should be set properly", async () => {
//       const { result } = renderHook(
//         () => useEnterDetailsStore((state) => state),
//         {
//           wrapper: createWrapper(),
//         }
//       )

//       const publicRate = roomRate.publicRate.localPrice.pricePerStay
//       const memberRate = roomRate.memberRate?.localPrice.pricePerStay ?? 0

//       const initialTotalPrice = publicRate * result.current.rooms.length
//       expect(result.current.totalPrice.local.price).toEqual(initialTotalPrice)

//       // room 1
//       await act(async () => {
//         result.current.actions.updateBedType(0)({
//           roomTypeCode: bedType.king.value,
//           description: bedType.king.description,
//         })
//         result.current.actions.updateBreakfast(0)(breakfastPackage)
//       })

//       let expectedTotalPrice =
//         initialTotalPrice + Number(breakfastPackage.localPrice.price)
//       expect(result.current.totalPrice.local.price).toEqual(expectedTotalPrice)

//       await act(async () => {
//         result.current.actions.updateDetails(0)(guestDetailsMember)
//       })

//       expectedTotalPrice =
//         memberRate + publicRate + Number(breakfastPackage.localPrice.price)
//       expect(result.current.totalPrice.local.price).toEqual(expectedTotalPrice)

//       // room 2
//       await act(async () => {
//         result.current.actions.updateBedType(1)({
//           roomTypeCode: bedType.king.value,
//           description: bedType.king.description,
//         })
//         result.current.actions.updateBreakfast(1)(breakfastPackage)
//       })

//       expectedTotalPrice =
//         memberRate + publicRate + Number(breakfastPackage.localPrice.price) * 2
//       expect(result.current.totalPrice.local.price).toEqual(expectedTotalPrice)

//       await act(async () => {
//         result.current.actions.updateDetails(1)(guestDetailsNonMember)
//       })

//       expect(result.current.totalPrice.local.price).toEqual(expectedTotalPrice)
//     })

//     test("room price should be set properly", async () => {
//       const { result } = renderHook(
//         () => useEnterDetailsStore((state) => state),
//         {
//           wrapper: createWrapper(),
//         }
//       )

//       const publicRate = roomRate.publicRate.localPrice.pricePerStay
//       const memberRate = roomRate.memberRate?.localPrice.pricePerStay ?? 0

//       let room1 = result.current.rooms[0]
//       expect(room1.room.roomPrice.perStay.local.price).toEqual(publicRate)

//       let room2 = result.current.rooms[0]
//       expect(room2.room.roomPrice.perStay.local.price).toEqual(publicRate)

//       await act(async () => {
//         result.current.actions.updateDetails(0)(guestDetailsMember)
//       })

//       room1 = result.current.rooms[0]
//       expect(room1.room.roomPrice.perStay.local.price).toEqual(memberRate)
//     })
//   })

//   describe("change room", () => {
//     test("changing to room with new bedtypes requires selecting bed again", async () => {
//       const { result: firstRun } = renderHook(
//         () => useEnterDetailsStore((state) => state),
//         {
//           wrapper: createWrapper({ bedTypes: [bedType.king, bedType.queen] }),
//         }
//       )

//       const selectedBedType = {
//         roomTypeCode: bedType.king.value,
//         description: bedType.king.description,
//       }

//       // add bedtype
//       await act(async () => {
//         firstRun.current.actions.updateBedType(0)(selectedBedType)
//       })

//       await act(async () => {
//         firstRun.current.actions.updateBreakfast(0)(false) // 'no breakfast' selected
//       })

//       await act(async () => {
//         firstRun.current.actions.updateDetails(0)(guestDetailsNonMember)
//       })

//       const updatedBooking = {
//         ...booking,
//         rooms: booking.rooms.map((r) => ({
//           ...r,
//           roomTypeCode: "NEW",
//         })),
//       }

//       // render again to change the bedtypes
//       const { result: secondRun } = renderHook(
//         () => useEnterDetailsStore((state) => state),
//         {
//           wrapper: createWrapper({
//             bookingParams: updatedBooking,
//             bedTypes: [bedType.single, bedType.queen],
//           }),
//         }
//       )

//       await waitFor(() => {
//         const secondRunRoom = secondRun.current.rooms[0]

//         // bed type should be unset since the bed types have changed
//         expect(secondRunRoom.room.bedType).toEqual(undefined)

//         // bed step should be unselected
//         expect(secondRunRoom.currentStep).toBe(StepEnum.selectBed)
//         expect(secondRunRoom.steps[StepEnum.selectBed].isValid).toBe(false)

//         // other steps should still be selected
//         expect(secondRunRoom.room.breakfast).toBe(false)
//         expect(secondRunRoom.steps[StepEnum.breakfast]?.isValid).toBe(true)
//         expect(secondRunRoom.room.guest).toEqual(guestDetailsNonMember)
//         expect(secondRunRoom.steps[StepEnum.details].isValid).toBe(true)
//       })
//     })

//     test("changing to room with single bedtype option should skip step", async () => {
//       const { result: firstRun } = renderHook(
//         () => useEnterDetailsStore((state) => state),
//         {
//           wrapper: createWrapper({ bedTypes: [bedType.king, bedType.queen] }),
//         }
//       )

//       const selectedBedType = {
//         roomTypeCode: bedType.king.value,
//         description: bedType.king.description,
//       }

//       // add bedtype
//       await act(async () => {
//         firstRun.current.actions.updateBedType(0)(selectedBedType)
//       })

//       await act(async () => {
//         firstRun.current.actions.updateBreakfast(0)(breakfastPackage)
//       })

//       const updatedBooking = {
//         ...booking,
//         rooms: booking.rooms.map((r) => ({
//           ...r,
//           roomTypeCode: "NEW",
//         })),
//       }

//       // render again to change the bedtypes
//       const { result: secondRun } = renderHook(
//         () => useEnterDetailsStore((state) => state),
//         {
//           wrapper: createWrapper({
//             bookingParams: updatedBooking,
//             bedTypes: [bedType.queen],
//           }),
//         }
//       )

//       await waitFor(() => {
//         const secondRunRoom = secondRun.current.rooms[0]

//         expect(secondRunRoom.room.bedType).toEqual({
//           roomTypeCode: bedType.queen.value,
//           description: bedType.queen.description,
//         })

//         expect(secondRunRoom.steps[StepEnum.selectBed].isValid).toBe(true)
//         expect(secondRunRoom.steps[StepEnum.breakfast]?.isValid).toBe(true)

//         expect(secondRunRoom.steps[StepEnum.details].isValid).toBe(false)
//         expect(secondRunRoom.currentStep).toBe(StepEnum.details)
//       })
//     })

//     test("if booking has changed, stored values should be discarded", async () => {
//       const { result: firstRun } = renderHook(
//         () => useEnterDetailsStore((state) => state),
//         {
//           wrapper: createWrapper({ bedTypes: [bedType.king, bedType.queen] }),
//         }
//       )

//       const selectedBedType = {
//         roomTypeCode: bedType.king.value,
//         description: bedType.king.description,
//       }

//       // add bedtype
//       await act(async () => {
//         firstRun.current.actions.updateBedType(0)(selectedBedType)
//       })

//       await act(async () => {
//         firstRun.current.actions.updateBreakfast(0)(breakfastPackage)
//       })

//       const updatedBooking = {
//         ...booking,
//         hotelId: "0001",
//         fromDate: "2030-01-01",
//         toDate: "2030-01-02",
//       }

//       renderHook(() => useEnterDetailsStore((state) => state), {
//         wrapper: createWrapper({
//           bookingParams: updatedBooking,
//           bedTypes: [bedType.queen],
//         }),
//       })

//       await waitFor(() => {
//         const storageItem = window.sessionStorage.getItem(detailsStorageName)
//         expect(storageItem).toBe(null)
//       })
//     })
//   })
// })
