import { AppSidebar } from "@/components/app-sidebar"
import { LocaleProvider } from "@/components/locale-provider"
import { translator } from "@/lib/i18n"
import type { MessageKey } from "@/lib/i18n/messages"
import { Separator } from "@/components/ui/separator"
import {
  SidebarInset,
  SidebarProvider,
  SidebarTrigger,
} from "@/components/ui/sidebar"
import { unreadCount } from "@/lib/services/notifications"
import { requireUser, type SignedIn } from "@/lib/services/session"

/**
 * The frame every screen sits in: sidebar, a header carrying the trigger and
 * the page title, and the content area.
 *
 * It is also the guard. Every screen behind a login renders inside this, so
 * asking here means no page can forget to ask. The alternative, the same check
 * repeated at the top of two dozen files, is a check that will be missing from
 * one of them within a month. A screen meant for a single tier calls
 * `requireTier` as well: that is a narrower question and it belongs to the page.
 *
 * The tier used to be a parameter, so the three states could be looked at side
 * by side before anything read a database. It comes from the session now.
 *
 * The content fills the width it is given. Capping it left a card floating far
 * from the navigation with several hundred pixels of nothing on either side,
 * which is a different fault from being pinned left, not a cure for it. A
 * screen that needs a reading measure sets one on its own text.
 */
export async function AppShell({
  title,
  user,
  children,
}: {
  /** A dictionary key, so a page cannot hand the shell an English sentence. */
  title: MessageKey
  /**
   * Passed in by a page that has already loaded it, so a screen calling
   * `requireTier` does not ask the same question twice in one request.
   */
  user?: SignedIn
  children: React.ReactNode
}) {
  const signedIn = user ?? (await requireUser())
  const t = translator(signedIn.language)
  /**
   * The badge on the notifications entry, read here because the sidebar is on
   * every screen and the count has to be the same on all of them. One indexed
   * count per request, which is what the index on (person_id, read_at) is for.
   */
  const unread = await unreadCount(signedIn.personId)

  return (
    // The language comes from the person and is handed down once. Every client
    // component below asks `useT()` and never asks who is reading.
    <LocaleProvider locale={signedIn.language}>
      <SidebarProvider>
        <AppSidebar user={signedIn} unread={unread} />
        <SidebarInset>
          <header className="flex h-16 shrink-0 items-center transition-[width,height] ease-linear group-has-data-[collapsible=icon]/sidebar-wrapper:h-12">
            <div className="flex w-full items-center gap-2 px-4">
              <SidebarTrigger className="-ml-1" />
              <Separator
                orientation="vertical"
                className="mr-2 data-vertical:h-4 data-vertical:self-auto"
              />
              <h1 className="text-base font-medium">{t(title)}</h1>
            </div>
          </header>
          <div className="flex w-full flex-1 flex-col gap-4 p-4 pt-0">
            {children}
          </div>
        </SidebarInset>
      </SidebarProvider>
    </LocaleProvider>
  )
}
