"use client"

import { useSession } from "next-auth/react"

import { BookingFlowContextProvider } from "@scandic-hotels/booking-flow/BookingFlowContextProvider"
import { logger } from "@scandic-hotels/common/logger"
import { trpc } from "@scandic-hotels/trpc/client"

import type { Session } from "next-auth"
import type { ComponentProps, ReactNode } from "react"

export function BookingFlowProviders({ children }: { children: ReactNode }) {
  const user = useBookingFlowUser()

  return (
    <BookingFlowContextProvider
      data={{
        isLoggedIn: user.state === "loaded" && !!user.data,
        user,
      }}
    >
      {children}
    </BookingFlowContextProvider>
  )
}

type BookingFlowContextData = ComponentProps<
  typeof BookingFlowContextProvider
>["data"]
type BookingFlowUser = BookingFlowContextData["user"]

function useBookingFlowUser(): BookingFlowUser {
  const { data: session } = useSession()
  const hasValidSession = isValidClientSession(session)

  const {
    data: euroBonusProfile,
    isError,
    isLoading,
  } = trpc.partner.sas.getEuroBonusProfile.useQuery(undefined, {
    enabled: hasValidSession,
  })

  if (isLoading) {
    return { state: "loading", data: undefined }
  }

  if (isError || !euroBonusProfile) {
    return { state: "error", data: undefined }
  }

  return {
    state: "loaded",
    data: {
      type: "partner-sas",
      partnerLoyaltyNumber: `EB${euroBonusProfile.eurobonusNumber}`,
      firstName: euroBonusProfile.firstName || null,
      lastName: euroBonusProfile.lastName || null,
      email: euroBonusProfile.email,
    },
  }
}

function isValidClientSession(session: Session | null) {
  if (!session) {
    return false
  }
  if (session.error) {
    logger.error(`Session error: ${session.error}`)
    return false
  }

  if (session.token.error) {
    logger.error(`Session token error: ${session.token.error}`)
    return false
  }
  if (session.token.expires_at && session.token.expires_at < Date.now()) {
    logger.error(`Session expired: ${session.token.expires_at}`)
    return false
  }

  return true
}
