'use client';

import {
  ComponentProps,
  Fragment,
  JSX,
  ReactNode,
  useEffect,
  useState,
} from 'react';
import ChecklistRow from '@/components/ChecklistRow';
import ChecklistGroup from '@/components/ChecklistGroup';
import { AppConfiguration } from '@/app/config';
import StatusIcon from '@/components/StatusIcon';
import { labelForStorage } from '@/platforms/storage';
import { testConnectionsAction } from '@/admin/actions';
import ErrorNote from '@/components/ErrorNote';
import SecretGenerator from '@/app/SecretGenerator';
import EnvVar from '@/components/EnvVar';
import AdminLink from '@/admin/AdminLink';
import ScoreCardContainer from '@/components/ScoreCardContainer';
import { CATEGORY_KEYS, DEFAULT_CATEGORY_KEYS } from '@/category';
import {
  AI_AUTO_GENERATED_FIELDS_ALL,
  AI_AUTO_GENERATED_FIELDS_DEFAULT,
} from '@/photo/ai';
import clsx from 'clsx/lite';
import Link from 'next/link';
import { PATH_FEED_JSON, PATH_RSS_XML } from '@/app/path';
import { APP_DEFAULT_SORT_BY, DEFAULT_SORT_BY_OPTIONS } from '@/photo/sort';
import {
  AdminConfigSection,
  ConfigSectionKey,
  getAdminConfigSections,
} from '.';
import ColorDot from '@/photo/color/ColorDot';
import { Oklch } from '@/photo/color/client';
import { getOrderedKeyListStatus } from '@/utility/key';
import { DEFAULT_SOCIAL_KEYS, SOCIAL_KEYS } from '@/social';
import MaskedScroll from '@/components/MaskedScroll';
import { IoLink } from 'react-icons/io5';

export default function AdminAppConfigurationClient({
  // Storage
  hasDatabase,
  isPostgresSslEnabled,
  hasRedisStorage,
  hasStorageProvider,
  hasVercelBlobStorage,
  hasCloudflareR2Storage,
  hasAwsS3Storage,
  hasMinioStorage,
  hasMultipleStorageProviders,
  currentStorage,
  // Auth
  hasAuthSecret,
  hasAdminUser,
  // Content
  locale,
  hasLocale,
  domain,
  hasDomain,
  metaTitle,
  isMetaTitleConfigured,
  metaDescription,
  isMetaDescriptionConfigured,
  navTitle,
  hasNavTitle,
  navCaption,
  hasNavCaption,
  pageAbout,
  hasPageAbout,
  // Performance
  isStaticallyOptimized,
  arePhotosStaticallyOptimized,
  arePhotoOGImagesStaticallyOptimized,
  arePhotoCategoriesStaticallyOptimized,
  arePhotoCategoryOgImagesStaticallyOptimized,
  areOriginalUploadsPreserved,
  hasImageQuality,
  imageQuality,
  isBlurEnabled,
  // AI
  hasOpenaiModel,
  hasOpenaiBaseUrl,
  isAiTextGenerationEnabled,
  aiTextAutoGeneratedFields,
  hasAiTextAutoGeneratedFields,
  // Location services
  hasLocationServices,
  // Categories
  hasCategoryVisibility,
  categoryVisibility,
  showCategoriesOnMobile,
  showCategoryImageHover,
  collapseSidebarCategories,
  hideTagsWithOnePhoto,
  // Sort
  hasDefaultSortBy,
  defaultSortBy,
  hasNavSortControl,
  navSortControl,
  isColorSortEnabled,
  hasColorSortConfiguration,
  colorSortStartingHue,
  colorSortChromaCutoff,
  isSortWithPriority,
  // Display
  showKeyboardShortcutTooltips,
  showExifInfo,
  showZoomControls,
  showTakenAtTimeHidden,
  showRepoLink,
  // Grid
  isGridHomepageEnabled,
  gridAspectRatio,
  hasGridAspectRatio,
  hasHighGridDensity,
  hasGridDensityPreference,
  // Design
  hasDefaultTheme,
  defaultTheme,
  arePhotosMatted,
  arePhotoMatteColorsConfigured,
  matteColor,
  matteColorDark,
  // Settings
  isGeoPrivacyEnabled,
  arePublicDownloadsEnabled,
  hasSocialKeys,
  socialKeys,
  areSiteFeedsEnabled,
  isOgTextBottomAligned,
  // Scripts & Analytics
  hasPageScriptUrls,
  pageScriptUrls,
  // Debugging
  isDebuggingEnabled,
  // Internal
  areInternalToolsEnabled,
  areAdminDebugToolsEnabled,
  isAdminSqlDebugEnabled,
  isAdminStorageDebugEnabled,
  // Auth
  secret,
  // Connection status
  databaseError,
  storageError,
  redisError,
  aiError,
  locationError,
  // Component props
  simplifiedView,
  isAnalyzingConfiguration,
}: AppConfiguration &
  { secret: string } &
  Partial<Awaited<ReturnType<typeof testConnectionsAction>>> & {
    simplifiedView?: boolean
    isAnalyzingConfiguration?: boolean
  }) {
  const [hasScrolled, setHasScrolled] = useState(false);

  useEffect(() => {
    const handleScroll = () => { setHasScrolled(true); };
    window.addEventListener('scroll', handleScroll);
    return () => {
      window.removeEventListener('scroll', handleScroll);
    };
  }, []);

  const renderContent = (content?: ReactNode) => content
    ? <div className={clsx(
      'my-1 px-2 py-1',
      'bg-dim rounded-lg',
    )}>
      {content}
    </div>
    : null;

  const renderEnvVars = (variables: string[]) =>
    <div className="pt-1 flex flex-col gap-0.5">
      {variables.map(variable =>
        <EnvVar key={variable} variable={variable} />)}
    </div>;

  const renderSubStatus = (
    type: ComponentProps<typeof StatusIcon>['type'],
    label: ReactNode,
    iconClassName = 'translate-y-[3.5px]',
  ) =>
    <div className="flex gap-2 translate-x-[-2.5px]">
      <StatusIcon {...{ type, className: iconClassName }} />
      <span className="min-w-0">
        {label}
      </span>
    </div>;
    
  const renderSubStatusWithEnvVar = (
    type: ComponentProps<typeof StatusIcon>['type'],
    variable: string,
  ) =>
    renderSubStatus(
      type,
      renderEnvVars([variable]),
      'translate-y-[7px]',
    );

  const renderOrderedKeyList = (
    selectedKeys: string[],
    acceptedKeys: readonly string[],
  ) =>
    <div>
      {getOrderedKeyListStatus({ selectedKeys, acceptedKeys })
        .map(({ label, selected }) =>
          <Fragment key={label}>
            {renderSubStatus(
              selected ? 'checked' : 'optional',
              selected
                ? label
                : <span className="text-dim">{label}</span>,
            )}
          </Fragment>)}
    </div>;

  const renderError = ({
    connection,
    message,
  }: {
    connection?: { provider: string, error: string }
    message?: string
  }) =>
    <ErrorNote className="mt-2 mb-3">
      {connection && <>
        {connection.provider} connection error: {`"${connection.error}"`}
      </>}
      {message}
    </ErrorNote>;

  const renderLink = (href: string, children?: ReactNode) =>
    <Link
      href={href}
      className="underline underline-offset-3 hover:no-underline"
      target="_blank"
    >
      {children || href}
    </Link>;

  const renderColorDot = (color: Oklch | string, includeTooltip?: boolean) =>
    <ColorDot
      color={color}
      className="size-3! ml-1"
      includeTooltip={includeTooltip}
    />;

  const renderCommaSeparatedList = (items: string[]) =>
    <>
      {'"'}
      {items.map((item, index) => <Fragment key={index}>
        {item}{index < items.length - 1 ? <>,&#8203;</> : <></>}
      </Fragment>)}
      {'"'}
    </>;

  const renderGroupContent = (key: ConfigSectionKey): JSX.Element => {
    switch (key) {
      case 'Storage':
        return <>
          <ChecklistRow
            title={hasDatabase && isAnalyzingConfiguration
              ? 'Testing database connection'
              : 'Setup database'}
            status={hasDatabase}
            isPending={hasDatabase && isAnalyzingConfiguration}
          >
            {databaseError && renderError({
              connection: { provider: 'Database', error: databaseError},
            })}
            {hasDatabase
              ? renderSubStatus(
                'checked',
                // eslint-disable-next-line max-len
                `Postgres: connected${!isPostgresSslEnabled ? ' (SSL disabled)' : ''}`,
              )
              : renderSubStatus('missing', <>
                Postgres:
                {' '}
                <AdminLink
                // eslint-disable-next-line max-len
                  href="https://vercel.com/docs/postgres#create-a-postgres-database"
                  externalIcon
                >
                  create database
                </AdminLink>
                {' '}
                and connect to project
              </>)}
          </ChecklistRow>
          <ChecklistRow
            title={
              hasStorageProvider && isAnalyzingConfiguration
                ? 'Testing storage connection'
                : !hasStorageProvider
                  ? 'Setup storage (one of the following)'
                  : hasMultipleStorageProviders
                  // eslint-disable-next-line max-len
                    ? `Setup storage (new uploads go to: ${labelForStorage(currentStorage)})`
                    : 'Setup storage'}
            status={hasStorageProvider}
            isPending={hasStorageProvider && isAnalyzingConfiguration}
          >
            {storageError && renderError({
              connection: { provider: 'Storage', error: storageError},
            })}
            <div>
              {hasVercelBlobStorage
                ? renderSubStatus('checked', 'Vercel Blob: connected')
                : renderSubStatus('optional', <>
                  {labelForStorage('vercel-blob')}:
                  {' '}
                  <AdminLink
                  // eslint-disable-next-line max-len
                    href="https://vercel.com/docs/storage/vercel-blob/quickstart#create-a-blob-store"
                    externalIcon
                  >
                    create store
                  </AdminLink>
                  {' '} 
                  and connect to project
                </>,
                )}
              {hasCloudflareR2Storage
                ? renderSubStatus('checked', 'Cloudflare R2: connected')
                : renderSubStatus('optional', <>
                  {labelForStorage('cloudflare-r2')}:
                  {' '}
                  <AdminLink
                  // eslint-disable-next-line max-len
                    href="https://github.com/sambecker/exif-photo-blog#cloudflare-r2"
                    externalIcon
                  >
                    create/configure bucket
                  </AdminLink>
                </>)}
              {hasAwsS3Storage
                ? renderSubStatus('checked', 'AWS S3: connected')
                : renderSubStatus('optional', <>
                  {labelForStorage('aws-s3')}:
                  {' '}
                  <AdminLink
                    href="https://github.com/sambecker/exif-photo-blog#aws-s3"
                    externalIcon
                  >
                    create/configure bucket
                  </AdminLink>
                </>)}
              {hasMinioStorage
                ? renderSubStatus('checked', 'MinIO: connected')
                : renderSubStatus('optional', <>
                  {labelForStorage('minio')}:
                  {' '}
                  <AdminLink
                    href="https://github.com/sambecker/exif-photo-blog#minio"
                    externalIcon
                  >
                    setup MinIO server
                  </AdminLink>
                </>)}
            </div>
          </ChecklistRow>
        </>;
      case 'Authentication':
        return <>
          <ChecklistRow
            title={!hasAuthSecret && isAnalyzingConfiguration
              ? 'Generating secret'
              : 'Setup auth'}
            status={hasAuthSecret}
            isPending={!hasAuthSecret && isAnalyzingConfiguration}
          >
            Store auth secret in environment variable:
            {!hasAuthSecret &&
            <div className="overflow-x-auto">
              <SecretGenerator {...{ secret }} />
            </div>}
            {renderEnvVars(['AUTH_SECRET'])}
          </ChecklistRow>
          <ChecklistRow
            title="Setup admin user"
            status={hasAdminUser}
          >
            Store admin email/password
            {' '}
            in environment variables:
            {renderEnvVars([
              'ADMIN_EMAIL',
              'ADMIN_PASSWORD',
            ])}
          </ChecklistRow>
        </>;
      case 'Content':
        return <>
          <ChecklistRow
            title="Configure language"
            status={hasLocale}
            optional
          >
            {renderContent(locale)}
            Store in environment variable
            (check README for
            {' '}
            <AdminLink
            // eslint-disable-next-line max-len
              href="https://github.com/sambecker/exif-photo-blog?tab=readme-ov-file#supported-languages"
            >
              supported languages
            </AdminLink>
            ):
            {renderEnvVars(['NEXT_PUBLIC_LOCALE'])}
          </ChecklistRow>
          <ChecklistRow
            title="Configure domain"
            status={hasDomain}
          >
            {renderContent(domain)}
            Store in environment variable
            (used in explicit share urls, seen in nav if no title is defined):
            {renderEnvVars(['NEXT_PUBLIC_DOMAIN'])}
          </ChecklistRow>
          <ChecklistRow
            title="Meta title"
            status={isMetaTitleConfigured}
            showWarning
          >
            {renderContent(metaTitle)}
            Store in environment variable
            (seen in search results and browser tab):
            {renderEnvVars(['NEXT_PUBLIC_META_TITLE'])}
          </ChecklistRow>
          {!simplifiedView && <>
            <ChecklistRow
              title="Meta description"
              status={isMetaDescriptionConfigured}
              optional
            >
              {renderContent(metaDescription)}
              Store in environment variable
              (seen in search results):
              {renderEnvVars(['NEXT_PUBLIC_META_DESCRIPTION'])}
            </ChecklistRow>
            <ChecklistRow
              title="Nav title"
              status={hasNavTitle}
              optional
            >
              {renderContent(navTitle)}
              Store in environment variable (replaces domain in top-right nav):
              {renderEnvVars(['NEXT_PUBLIC_NAV_TITLE'])}
            </ChecklistRow>
            <ChecklistRow
              title="Nav caption"
              status={hasNavCaption}
              optional
            >
              {hasNavCaption && renderContent(navCaption)}
              Store in environment variable
              (seen in top-right nav, under title):
              {renderEnvVars(['NEXT_PUBLIC_NAV_CAPTION'])}
            </ChecklistRow>
            <ChecklistRow
              title="Page about"
              status={hasPageAbout}
              optional
            >
              {hasPageAbout && renderContent(pageAbout)}
              Store in environment variable (seen in sidebar):
              {renderEnvVars(['NEXT_PUBLIC_PAGE_ABOUT'])}
            </ChecklistRow>
          </>}
        </>;
      case 'External Services':
        return <>
          <ChecklistRow
            title={hasRedisStorage && isAnalyzingConfiguration
              ? 'Testing Redis connection'
              : 'Rate limiting'}
            status={hasRedisStorage}
            isPending={hasRedisStorage && isAnalyzingConfiguration}
            showWarning={isAiTextGenerationEnabled || hasLocationServices}
            optional
          >
            {redisError && renderError({
              connection: { provider: 'Redis', error: redisError},
            })}
            Create Upstash Redis store from storage tab
            on Vercel dashboard and connect to this project
            to enable rate limiting on external services
          </ChecklistRow>
          <ChecklistRow
            title={isAiTextGenerationEnabled && isAnalyzingConfiguration
              ? 'Testing OpenAI connection'
              : 'OpenAI'}
            status={isAiTextGenerationEnabled}
            isPending={isAiTextGenerationEnabled && isAnalyzingConfiguration}
            optional
          >
            {aiError && renderError({
              connection: { provider: 'OpenAI', error: aiError},
            })}
            Store OpenAI secret key in order to enable AI-generated
            text descriptions, including an invisible field called
            {' '}
            {'"Semantic Description"'}, which supports CMD-K search
            and image accessibility:
            {renderEnvVars(['OPENAI_SECRET_KEY'])}
          </ChecklistRow>
          <ChecklistRow
            title={hasLocationServices && isAnalyzingConfiguration
              ? 'Testing Google Places connection'
              : 'Google Places'}
            status={hasLocationServices}
            isPending={hasLocationServices && isAnalyzingConfiguration}
            optional
          >
            {locationError && renderError({
              connection: { provider: 'Google Places', error: locationError},
            })}
            Store Google Places API key in order to add location meta
            to entities like albums:
            {renderEnvVars(['GOOGLE_PLACES_API_KEY'])}
          </ChecklistRow>
        </>;
      case 'AI Text':
        return <>
          <ChecklistRow
            title={'Auto-generated text fields'}
            status={hasAiTextAutoGeneratedFields}
            optional
          >
            <div>
              {hasAiTextAutoGeneratedFields &&
              AI_AUTO_GENERATED_FIELDS_ALL.map(field =>
                <Fragment key={field}>
                  {renderSubStatus(
                    aiTextAutoGeneratedFields.includes(field)
                      ? 'checked'
                      : 'optional',
                    field,
                  )}
                </Fragment>)}
            </div>
            Comma-separated fields to auto-generate when
            uploading photos. Accepted values: title, caption,
            tags, description, all, or none
            {' '}
            (default: {renderCommaSeparatedList(
              AI_AUTO_GENERATED_FIELDS_DEFAULT,
            )}):
            {renderEnvVars(['AI_TEXT_AUTO_GENERATED_FIELDS'])}
          </ChecklistRow>
          <ChecklistRow
            title="Model override"
            status={hasOpenaiModel}
            optional
          >
            Store model in environment variable to use
            alternate OpenAI model
            {' '}
            {'(set to \'compatible\' to use gpt-4o):'}
            {renderEnvVars(['OPENAI_MODEL'])}
          </ChecklistRow>
          <ChecklistRow
            title="Base URL override (experimental)"
            status={hasOpenaiBaseUrl}
            optional
          >
            Store base URL in environment variable to use
            alternate OpenAI-compatible providers:
            {renderEnvVars(['OPENAI_BASE_URL'])}
          </ChecklistRow>
        </>;
      case 'Performance':
        return <>
          <ChecklistRow
            title="Static optimization"
            status={isStaticallyOptimized}
            optional
          >
            Set environment variable to {'"1"'} to make site more responsive
            by enabling static optimization
            (i.e., rendering pages and images at build time):
            <div>
              {renderSubStatusWithEnvVar(
                arePhotosStaticallyOptimized ? 'checked' : 'optional',
                'NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTOS',
              )}
              {renderSubStatusWithEnvVar(
                arePhotoOGImagesStaticallyOptimized ? 'checked' : 'optional',
                'NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTO_OG_IMAGES',
              )}
              {renderSubStatusWithEnvVar(
                arePhotoCategoriesStaticallyOptimized ? 'checked' : 'optional',
                'NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTO_CATEGORIES',
              )}
              {renderSubStatusWithEnvVar(
              // eslint-disable-next-line max-len
                arePhotoCategoryOgImagesStaticallyOptimized ? 'checked' : 'optional',
                'NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTO_CATEGORY_OG_IMAGES',
              )}
            </div>
          </ChecklistRow>
          <ChecklistRow
            title="Preserve original uploads"
            status={areOriginalUploadsPreserved}
            optional
          >
            Set environment variable to {'"1"'} to prevent
            image uploads being compressed before storing:
            {renderEnvVars(['NEXT_PUBLIC_PRESERVE_ORIGINAL_UPLOADS'])}
          </ChecklistRow>
          <ChecklistRow
            title={`Image quality: ${imageQuality}`}
            status={hasImageQuality}
            optional
          >
            Set environment variable from {'"1-100"'}
            {' '}
            to control the quality of large photos
            ({'"100"'} represents highest quality/largest size):
            {renderEnvVars(['NEXT_PUBLIC_IMAGE_QUALITY'])}
          </ChecklistRow>
          <ChecklistRow
            title="Image blur"
            status={isBlurEnabled}
            optional
          >
            Set environment variable to {'"1"'} to prevent
            image blur data being stored and displayed:
            {renderEnvVars(['NEXT_PUBLIC_BLUR_DISABLED'])}
          </ChecklistRow> 
        </>;
      case 'Categories':
        return <>
          <ChecklistRow
            title="Visibility and ordering"
            status={hasCategoryVisibility}
            optional
          >
            {renderOrderedKeyList(categoryVisibility, CATEGORY_KEYS)}
            <div>
              Configure order and visibility of categories
              (seen in grid sidebar and CMD-K results)
              by storing comma-separated values
              (default: {renderCommaSeparatedList(DEFAULT_CATEGORY_KEYS)}):
            </div>
            {renderEnvVars(['NEXT_PUBLIC_CATEGORY_VISIBILITY'])}
          </ChecklistRow>
          <ChecklistRow
            title="Show on mobile"
            status={showCategoriesOnMobile}
            optional
          >
            <div className="flex flex-col gap-2">
              <div>
                Set environment variable to {'"1"'} to prevent categories
                displaying on mobile grid view:
                {renderEnvVars(['NEXT_PUBLIC_HIDE_CATEGORIES_ON_MOBILE'])}
              </div>
            </div>
          </ChecklistRow>
          <ChecklistRow
            title="Show image hovers"
            status={showCategoryImageHover}
            optional
          >
            <div className="flex flex-col gap-2">
              <div>
                Set environment variable to {'"1"'} to prevent images
                displaying when hovering over category links:
                {renderEnvVars(['NEXT_PUBLIC_HIDE_CATEGORY_IMAGE_HOVERS'])}
              </div>
            </div>
          </ChecklistRow>
          <ChecklistRow
            title="Collapsible sidebar"
            status={collapseSidebarCategories}
            optional
          >
            Set environment variable to {'"1"'} to always show
            expanded category content
            {renderEnvVars(['NEXT_PUBLIC_EXHAUSTIVE_SIDEBAR_CATEGORIES'])}
          </ChecklistRow>
          <ChecklistRow
            title="Hide tags with only 1 photo"
            status={hideTagsWithOnePhoto}
            optional
          >
            Set environment variable to {'"1"'} to only show tags
            with 2 or more photos
            {renderEnvVars(['NEXT_PUBLIC_HIDE_TAGS_WITH_ONE_PHOTO'])}
          </ChecklistRow>
        </>;
      case 'Sorting':
        return <>
          <ChecklistRow
            title="Default order"
            status={hasDefaultSortBy}
            optional
          >
            <div>
              {DEFAULT_SORT_BY_OPTIONS
                .map(({sortBy, configKey }) =>
                  <Fragment key={ sortBy }>
                    {renderSubStatus(
                      sortBy === defaultSortBy ? 'checked' : 'optional',
                      `${configKey}${sortBy === APP_DEFAULT_SORT_BY
                        ? ' (default)'
                        : ''}`,
                    )}
                  </Fragment>)}
            </div>
            Change default sort on grid/full homepages
            {renderEnvVars(['NEXT_PUBLIC_DEFAULT_SORT'])}
          </ChecklistRow>
          <ChecklistRow
            title={`Nav sort control: ${navSortControl}`}
            status={hasNavSortControl}
            optional
          >
            Set environment variable to {'"none"'}, {'"toggle"'} (default),
            or {'"menu"'}, to control sort UI on grid/full homepages:
            {renderEnvVars(['NEXT_PUBLIC_NAV_SORT_CONTROL'])}
          </ChecklistRow>
          <ChecklistRow
            title="Color sort"
            status={isColorSortEnabled}
            experimental
            optional
          >
            Set environment variable to {'"1"'} to enable color-based sorting
            (forces nav sort control to {'"menu,"'} flags photos missing
            color data in admin dashboard)—color identification
            benefits greatly from AI being enabled:
            {renderEnvVars([
              'NEXT_PUBLIC_COLOR_SORT',
            ])}
          </ChecklistRow>
          <ChecklistRow
            title="Color sort configuration"
            status={hasColorSortConfiguration}
            experimental
            optional
          >
            Configure which colors start first
            (accepts a hue of 0 to 360, default: 80)
            and which are considered sufficiently vibrant
            (accepts a chroma of 0 to 0.37, default: 0.05):
            <div>
              <EnvVar
                variable="NEXT_PUBLIC_COLOR_SORT_STARTING_HUE"
                value={colorSortStartingHue}
                accessory={renderColorDot({
                  l: 0.85,
                  c: 0.15,
                  h: colorSortStartingHue,
                }, false)}
              />
              <EnvVar
                variable="NEXT_PUBLIC_COLOR_SORT_CHROMA_CUTOFF"
                value={colorSortChromaCutoff}
              />
            </div>
          </ChecklistRow>
          <ChecklistRow
            title="Priority-based"
            status={isSortWithPriority}
            optional
          >
            Set environment variable to {'"1"'} to take priority field
            into account when sorting photos (enabling may have
            performance consequences):
            {renderEnvVars(['NEXT_PUBLIC_PRIORITY_BASED_SORTING'])}
          </ChecklistRow>
        </>;
      case 'Display':
        return <>
          <ChecklistRow
            title="Show keyboard shortcut tooltips"
            status={showKeyboardShortcutTooltips}
            optional
          >
            Set environment variable to {'"1"'} to hide keyboard shortcut
            tooltips in areas like the main nav, and previous/next photo links:
            {renderEnvVars(['NEXT_PUBLIC_HIDE_KEYBOARD_SHORTCUT_TOOLTIPS'])}
          </ChecklistRow>
          <ChecklistRow
            title="Show EXIF data"
            status={showExifInfo}
            optional
          >
            Set environment variable to {'"1"'} to hide EXIF data:
            {renderEnvVars(['NEXT_PUBLIC_HIDE_EXIF_DATA'])}
          </ChecklistRow>
          <ChecklistRow
            title="Show zoom controls"
            status={showZoomControls}
            optional
          >
            Set environment variable to {'"1"'} to hide
            fullscreen photo zoom controls:
            {renderEnvVars(['NEXT_PUBLIC_HIDE_ZOOM_CONTROLS'])}
          </ChecklistRow>
          <ChecklistRow
            title="Show taken at time"
            status={showTakenAtTimeHidden}
            optional
          >
            Set environment variable to {'"1"'} to hide
            taken at time from photo meta:
            {renderEnvVars(['NEXT_PUBLIC_HIDE_TAKEN_AT_TIME'])}
          </ChecklistRow>
          <ChecklistRow
            title="Show repo link"
            status={showRepoLink}
            optional
          >
            Set environment variable to {'"1"'} to hide footer link:
            {renderEnvVars(['NEXT_PUBLIC_HIDE_REPO_LINK'])}
          </ChecklistRow>
        </>;
      case 'Grid':
        return <>
          <ChecklistRow
            title="Grid homepage"
            status={isGridHomepageEnabled}
            optional
          >
            Set environment variable to {'"1"'} to show grid layout
            on homepage:
            {renderEnvVars(['NEXT_PUBLIC_GRID_HOMEPAGE'])}
          </ChecklistRow>
          <ChecklistRow
            title={`Grid aspect ratio: ${gridAspectRatio}`}
            status={hasGridAspectRatio}
            optional
          >
            Set environment variable to any number to enforce aspect ratio
            {' '}
            (default is {'"1"'}, i.e., square)—set to {'"0"'} to disable:
            {renderEnvVars(['NEXT_PUBLIC_GRID_ASPECT_RATIO'])}
          </ChecklistRow>
          <ChecklistRow
            title={`Grid density: ${hasHighGridDensity ? 'high' : 'low'}`}
            status={hasGridDensityPreference}
            optional
          >
            Set environment variable to {'"1"'} to ensure large thumbnails
            on photo grid views (if not configured, density is based on
            aspect ratio):
            {renderEnvVars(['NEXT_PUBLIC_SHOW_LARGE_THUMBNAILS'])}
          </ChecklistRow> 
        </>;
      case 'Design':
        return <>
          <ChecklistRow
            title={`Default theme: ${defaultTheme}`}
            status={hasDefaultTheme}
            optional
          >
            {'Set environment variable to \'light\' or \'dark\''}
            {' '}
            to configure initial theme
            {' '}
            (defaults to {'\'system\''}):
            {renderEnvVars(['NEXT_PUBLIC_DEFAULT_THEME'])}
          </ChecklistRow>
          <ChecklistRow
            title="Photo matting"
            status={arePhotosMatted}
            optional
          >
            Set environment variable to {'"1"'} to constrain the size
            {' '}
            of each photo, and display a surrounding border:
            <div className="pt-1 flex flex-col gap-1">
              <EnvVar variable="NEXT_PUBLIC_MATTE_PHOTOS" />
            </div>
          </ChecklistRow>
          <ChecklistRow
            title="Custom photo matting colors"
            status={arePhotoMatteColorsConfigured}
            optional
          >
            Set environment variable hex values (e.g., #cccccc)
            to override matte colors:
            <div className="pt-1 flex flex-col gap-1">
              <EnvVar
                variable="NEXT_PUBLIC_MATTE_COLOR"
                accessory={matteColor && renderColorDot(matteColor)}
              />
              <EnvVar
                variable="NEXT_PUBLIC_MATTE_COLOR_DARK"
                accessory={matteColorDark && renderColorDot(matteColorDark)}
              />
            </div>
          </ChecklistRow>
        </>;
      case 'Settings':
        return <>
          <ChecklistRow
            title="Geo privacy"
            status={isGeoPrivacyEnabled}
            optional
          >
            Set environment variable to {'"1"'} to disable
            collection/display of location-based data:
            {renderEnvVars(['NEXT_PUBLIC_GEO_PRIVACY'])}
          </ChecklistRow>
          <ChecklistRow
            title="Public downloads"
            status={arePublicDownloadsEnabled}
            optional
          >
            Set environment variable to {'"1"'} to enable
            public photo downloads for all visitors:
            {renderEnvVars(['NEXT_PUBLIC_ALLOW_PUBLIC_DOWNLOADS'])}
          </ChecklistRow>
          <ChecklistRow
            title="Share modal options"
            status={hasSocialKeys}
            optional
          >
            {renderOrderedKeyList(socialKeys, SOCIAL_KEYS)}
            <div>
              Configure order and visibility of share modal 
              options by storing comma-separated values
              (accepts {'"all"'} or {'"none"'},
              defaults to {renderCommaSeparatedList(DEFAULT_SOCIAL_KEYS)})
            </div>
            {renderEnvVars(['NEXT_PUBLIC_SOCIAL_NETWORKS'])}
          </ChecklistRow>
          <ChecklistRow
            title="Site feeds (JSON/RSS)"
            status={areSiteFeedsEnabled}
            optional
          >
            Set environment variable to {'"1"'} to enable feeds at
            {' '}
            {renderLink(PATH_FEED_JSON)} and {renderLink(PATH_RSS_XML)}:
            {renderEnvVars(['NEXT_PUBLIC_SITE_FEEDS'])}
          </ChecklistRow>
          <ChecklistRow
            title="Legacy OG text alignment"
            status={isOgTextBottomAligned}
            optional
          >
            Set environment variable to {'"BOTTOM"'} to
            keep OG image text bottom aligned (default is {'"top"'}):
            {renderEnvVars(['NEXT_PUBLIC_OG_TEXT_ALIGNMENT'])}
          </ChecklistRow>
        </>;
      case 'Scripts & Analytics':
        return <>
          <ChecklistRow
            title="Custom page scripts"
            status={hasPageScriptUrls}
            optional
          >
            {pageScriptUrls.length > 0 &&
              <div className="mt-2 text-xs space-y-1.5">
                {pageScriptUrls.map(url =>
                  <MaskedScroll
                    key={url}
                    className={clsx(
                      'inline-flex items-center gap-1',
                      'bg-dim rounded-md px-1.5 py-0.5',
                    )}
                    direction="horizontal"
                  >
                    <IoLink size={14} className="shrink-0 translate-y-[0.5px]"/>
                    <span className="font-medium text-nowrap">
                      {url}
                    </span>
                  </MaskedScroll>)}
              </div>}
            Set environment variable to comma-separated list of URLs
            to be added to the bottom of the body tag via {'"next/script"'}:
            {renderEnvVars(['PAGE_SCRIPT_URLS'])}
          </ChecklistRow>
        </>;
      case 'Debugging':
        return <>
          <ChecklistRow
            title="Debug outputs"
            status={isDebuggingEnabled}
            optional
          >
            Set environment variable to {'"1"'} to disable build identifier
            and admin configuration export:
            {renderEnvVars(['DISABLE_DEBUG_OUTPUTS'])}
          </ChecklistRow>
        </>;
      case 'Internal':
        return <>
          <ChecklistRow
            title="Debug tools"
            status={areAdminDebugToolsEnabled}
            optional
          >
            Set environment variable to {'"1"'} to temporarily enable
            features like photo matting, baseline grid, etc.:
            {renderEnvVars(['ADMIN_DEBUG_TOOLS'])}
          </ChecklistRow>
          <ChecklistRow
            title="SQL debugging"
            status={isAdminSqlDebugEnabled}
            optional
          >
            Set environment variable to {'"1"'} to enable
            console output for all sql queries:
            {renderEnvVars(['ADMIN_SQL_DEBUG'])}
          </ChecklistRow>
          <ChecklistRow
            title="Storage debugging"
            status={isAdminStorageDebugEnabled}
            optional
          >
            Set environment variable to {'"1"'} to enable
            storage debugging:
            {renderEnvVars(['ADMIN_STORAGE_DEBUG'])}
          </ChecklistRow>
        </>;
    }
  };

  return (
    <ScoreCardContainer>
      {getAdminConfigSections(areInternalToolsEnabled, simplifiedView)
        .map((section) => (
          <ChecklistGroup
            key={section.title}
            title={section.title}
            titleShort={(section as AdminConfigSection).titleShort}
            icon={section.icon}
            optional={!section.required}
            updateHashOnVisible={hasScrolled && !simplifiedView}
          >
            {renderGroupContent(section.title)}
          </ChecklistGroup>
        ))}
      <div className="pl-11 pr-2 sm:pr-11 mt-4 md:mt-7">
        <div>
          Changes to environment variables require a new deployment
          to take effect
        </div>
      </div>
    </ScoreCardContainer>
  );
}
