import type {Profile, SessionWithProfile} from '@/models/users'
import {cookies} from 'next/headers'
import type {Role, Session} from '@/generated/prisma/client'
import {extendSession, getSessionProfile} from '@/dal/users'

// *********************************************************************************************************************
//                                                   UTILS
// *********************************************************************************************************************

export async function getSessionFromCookie(): Promise<SessionWithProfile | null> {
  const sessionId = await getSessionId()
  return sessionId ? await getSessionProfile(sessionId) : null
}

export async function getSessionProfileFromCookie(): Promise<Profile | null> {
  const session = await getSessionFromCookie()
  return session?.user ?? null
}

export async function getSessionProfileFromCookieOrThrow(): Promise<Profile> {
  const session = await getSessionFromCookie()

  if (!session) {
    throw new Error("Couldn't retrieve the user's profile in getSessionProfileFromCookieOrThrow.")
  }

  return session?.user ?? null
}

export async function extendSessionAndSetCookie(id: string, role: Role): Promise<void> {
  const extendedSession = await extendSession(id, role)
  await setSessionCookie(extendedSession)
}

// *********************************************************************************************************************
//                                                   COOKIES
// *********************************************************************************************************************

const cookieName = 'sessionId'

/**
 * Add a session cookie to the request which includes the user's session id.
 *
 * @param session The session for which to create a session.
 */
export async function setSessionCookie(session: Session): Promise<void> {
  const awaitedCookies = await cookies()
  awaitedCookies.set({
    name: cookieName,
    value: session.id,
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'strict',
    path: '/',
    expires: session.activeUntil,
  })
}

/**
 * Remove the active session cookie (if there is one).
 */
export async function clearSessionCookie(): Promise<void> {
  const awaitedCookies = await cookies()
  awaitedCookies.delete(cookieName)
}

/**
 * Retrieve the id of the current session if there is one.
 */
export async function getSessionId(): Promise<string | undefined> {
  return (await cookies()).get(cookieName)?.value
}
