import { type BasicAccessCheckProps } from '../core/access-check-shared'
import { isPendingAccessCheckState, useAccessCheckStateInternal } from '../runtime/use-access-check-state'
import { AccessDeniedView } from '../ui/AccessDeniedView'

type PageAccessGuardFallbackProp = React.ReactNode | ((defaultFallback: React.ReactNode) => React.ReactNode)

interface PageAccessGuardProps extends BasicAccessCheckProps {
  /**
   * Content to render when access is denied.
   *
   * Defaults to `<AccessDeniedView />`.
   *
   * - If `fallback` is a ReactNode, it fully overrides the default fallback.
   * - If `fallback` is a function, it receives the default fallback (i.e. `<AccessDeniedView />`)
   *   and returns what to render. This is useful for wrapping the default denied UI with a page shell/layout.
   */
  fallback?: PageAccessGuardFallbackProp
  /**
   * Page content to render when access is granted.
   */
  children?: React.ReactNode
}

/**
 * Page-level access guard with default "Access Denied" page fallback.
 *
 * Use this at the root of route components to protect entire pages.
 * When access is denied, shows a full-page `AccessDeniedView` component.
 *
 * @example
 * // Basic page protection
 * function UserManagementPage() {
 *   return (
 *     <PageAccessGuard id="OrgUsersAction">
 *       <UserList />
 *       <AddUserButton />
 *     </PageAccessGuard>
 *   )
 * }
 *
 * @example
 * // Wrap denied view in page layout
 * function SettingsPage() {
 *   return (
 *     <PageAccessGuard
 *       id="OrgSettingsGate"
 *       fallback={(defaultDenied) => (
 *         <PageLayout>
 *           <PageHeader title="Settings" />
 *           {defaultDenied}
 *         </PageLayout>
 *       )}
 *     >
 *       <SettingsContent />
 *     </PageAccessGuard>
 *   )
 * }
 *
 * @example
 * // Custom denied page
 * function BillingPage() {
 *   return (
 *     <PageAccessGuard
 *       id="OrgBillingGate"
 *       fallback={
 *         <CustomDeniedView
 *           title="Billing Access Required"
 *           message="Contact your org admin for billing access"
 *         />
 *       }
 *     >
 *       <BillingDashboard />
 *     </PageAccessGuard>
 *   )
 * }
 */
export const PageAccessGuard = ({ fallback, children, ...restProps }: PageAccessGuardProps) => {
  const state = useAccessCheckStateInternal(restProps.id, restProps.scopeProps)
  const defaultFallback = <AccessDeniedView mode={isPendingAccessCheckState(state) ? 'loading' : 'denied'} />
  const resolvedFallback = typeof fallback === 'function' ? fallback(defaultFallback) : (fallback ?? defaultFallback)

  if (state.status === 'resolved' && state.accessible) {
    return <>{children}</>
  }

  return <>{resolvedFallback}</>
}
