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

import { dt } from "@/lib/dt"
import { createDetailsStore } from "@/stores/enter-details"
import {
  calcTotalPrice,
  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 type { DetailsProviderProps } from "@/types/providers/enter-details"
import type { InitialState } from "@/types/stores/enter-details"

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

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

  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 room = rooms[idx]

      if (!storedRoom.room?.bedType) {
        return storedRoom
      }

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

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

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

    const canProceedToPayment = updatedRooms.every((room) => room.isComplete)

    const nights = dt(booking.toDate).diff(booking.fromDate, "days")
    const currency =
      updatedRooms[0].room.roomRate.publicRate.localPrice.currency
    const totalPrice = calcTotalPrice(updatedRooms, currency, !!user, nights)

    storeRef.current?.setState({
      activeRoom: storedValues.activeRoom,
      canProceedToPayment,
      rooms: updatedRooms,
      totalPrice,
    })
  }, [booking, rooms, user])

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