// The admin shell — and the AUTH GATE. This nested layout wraps every page
// under `/admin`, and its `loader` runs server-side BEFORE the page renders, so
// it's the right seam to validate the session. Throwing RedirectError
// short-circuits the subtree (303 + Location on SSR; replace-nav on the client).
// Pages under here are `renderMode: 'ssr'` so the gate runs per request.
//
// The sidebar is DRIVEN BY THE API'S CAPABILITY MAP: useCapabilityManifest +
// deriveEntityAdmins discover every entity at runtime, so point the admin at any
// api and the nav adapts — no per-entity code. The undo bar wraps the
// __voltro.undo.* built-ins (requires undo capture on; the dev default).
import type { ReactNode } from 'react'
import { RedirectError, useLoaderData, useLocation, type LoaderFn } from '@voltro/web'
import {
  useCapabilityManifest,
  deriveEntityAdmins,
  useUndoLog,
  PermissionProvider,
} from '@voltro/client'
import { T, useLocale, useT } from '@voltro/i18n'
import { LocaleSwitcher } from '@voltro/ui-shadcn'
import { APP_NAME } from '../../config'
import { isSignedIn } from '../../lib/auth'
import { DEMO_SCOPES } from '../../lib/admin'

const LOCALES = [
  { code: 'en', label: 'English' },
  { code: 'de', label: 'Deutsch' },
]

export const renderMode = 'ssr' as const

interface AdminData {
  readonly user: { readonly name: string }
}

export const loader: LoaderFn<AdminData> = async ({ headers }) => {
  if (!isSignedIn(headers)) {
    throw new RedirectError('/login?from=/admin')
  }
  return { user: { name: 'Demo Admin' } }
}

// The undo bar — split out so a deployment running with VOLTRO_UNDO=off (no
// __voltro.undo.* built-ins) can delete just these lines.
const UndoBar = (): ReactNode => {
  const undo = useUndoLog('app')
  return (
    <>
      <button type="button" className="btn ghost" disabled={!undo.canUndo} onClick={() => void undo.undoLast()}>
        <T id="admin.undo" />
      </button>
      <button type="button" className="btn ghost" disabled={!undo.canRedo} onClick={() => void undo.redoLast()}>
        <T id="admin.redo" />
      </button>
    </>
  )
}

export default function AdminLayout({ children }: { readonly children: ReactNode }): ReactNode {
  const { user } = useLoaderData<AdminData>()
  const pathname = useLocation()
  const locale = useLocale()
  const langLabel = useT('lang.label')
  const { manifest, loading } = useCapabilityManifest('app')
  const entities = manifest ? deriveEntityAdmins(manifest) : []

  const navItem = (href: string, label: ReactNode): ReactNode => (
    <a key={href} href={href} aria-current={pathname === href ? 'page' : undefined}>{label}</a>
  )

  return (
    // PermissionProvider feeds the current subject's scopes to useAccessDecision
    // across the admin, which judges them against each procedure's OWN declared
    // guards. DEMO scopes here — swap for your session's (see lib/admin.ts).
    <PermissionProvider scopes={DEMO_SCOPES}>
      <div className="admin">
        <aside>
          <div className="brand">{APP_NAME}</div>
          <nav>
            {navItem('/admin', <T id="admin.nav.overview" />)}
            {loading && entities.length === 0 ? <span className="muted" style={{ padding: '0.35rem 0.6rem', fontSize: '0.85rem' }}><T id="admin.nav.discovering" /></span> : null}
            {entities.map((e) => navItem(`/admin/${e.table}`, e.table))}
            <a href="/"><T id="admin.nav.backToSite" /></a>
          </nav>
        </aside>
        <main>
          <div className="topbar">
            <strong>{user.name}</strong>
            <span className="spacer" />
            <UndoBar />
            <LocaleSwitcher locales={LOCALES} current={locale} ariaLabel={langLabel} />
          </div>
          {children}
        </main>
      </div>
    </PermissionProvider>
  )
}
