"use client"
import { useEffect, useRef } from "react"

import { createDetailsStore } from "@/stores/enter-details"
import {
  checkIsSameBedTypes,
  checkIsSameBooking as checkIsSameBooking,
  clearSessionStorage,
  readFromSessionStorage,
} from "@/stores/enter-details/helpers"

import { DetailsContext } from "@/contexts/Details"

import type { DetailsStore } from "@/types/contexts/enter-details"
import { StepEnum } from "@/types/enums/step"
import type { DetailsProviderProps } from "@/types/providers/enter-details"
import type { InitialState } from "@/types/stores/enter-details"

export default function EnterDetailsProvider({
  booking,
  showBreakfastStep,
  children,
  roomsData,
  searchParamsStr,
  user,
  vat,
}: DetailsProviderProps) {
  const storeRef = useRef<DetailsStore>()
  if (!storeRef.current) {
    const initialData: InitialState = {
      booking,
      rooms: roomsData
        .filter((r) => r.bedTypes?.length) // TODO: how to handle room without bedtypes?
        .map((room) => ({
          roomFeatures: room.packages,
          roomRate: room.roomRate,
          roomType: room.roomType,
          cancellationText: room.cancellationText,
          rateDetails: room.rateDetails,
          bedType:
            room.bedTypes?.length === 1
              ? {
                  roomTypeCode: room.bedTypes[0].value,
                  description: room.bedTypes[0].description,
                }
              : undefined,
        })),
      vat,
    }

    if (!showBreakfastStep) {
      initialData.breakfast = false
    }

    storeRef.current = createDetailsStore(initialData, searchParamsStr, user)
  }

  useEffect(() => {
    const storedValues = readFromSessionStorage()
    if (!storedValues) {
      return
    }
    const isSameBooking = checkIsSameBooking(storedValues.booking, booking)
    if (!isSameBooking) {
      clearSessionStorage()
      return
    }

    const updatedRooms = storedValues.rooms.map((storedRoom, idx) => {
      const currentRoom = booking.rooms[idx]
      const roomData = roomsData[idx]

      if (!storedRoom.bedType) {
        return storedRoom
      }

      const isSameBedTypes = checkIsSameBedTypes(
        storedRoom.bedType.roomTypeCode,
        currentRoom.roomTypeCode
      )
      if (isSameBedTypes) {
        return storedRoom
      }

      if (roomData?.bedTypes?.length === 1 && roomData.bedTypes[0]) {
        return {
          ...storedRoom,
          bedType: {
            roomTypeCode: roomData.bedTypes[0].value,
            description: roomData.bedTypes[0].description,
          },
        }
      }

      // Remove bed type selection if bedtypes change
      return {
        ...storedRoom,
        bedType: undefined,
      }
    })

    const updatedProgress = {
      ...storedValues.bookingProgress,
      roomStatuses: storedValues.bookingProgress.roomStatuses.map(
        (status, idx) => {
          const hasValidBedType = Boolean(updatedRooms[idx].bedType)
          if (hasValidBedType) return status

          return {
            ...status,
            steps: {
              ...status.steps,
              [StepEnum.selectBed]: {
                step: StepEnum.selectBed,
                isValid: false,
              },
            },
            currentStep: StepEnum.selectBed,
            isComplete: false,
          }
        }
      ),
    }

    storeRef.current?.setState({
      rooms: updatedRooms,
      bookingProgress: updatedProgress,
    })
  }, [booking, roomsData])

  return (
    <DetailsContext.Provider value={storeRef.current}>
      {children}
    </DetailsContext.Provider>
  )
}
